Chapitre 12 sur 13

Git : checkout, switch, reset et restore

Laisser un commentaire

Les commandes checkout et reset ont beaucoup semé la confusion parmi les utilisateurs de Git. Elles permettent de très nombreuses choses et peuvent dans certains cas être utilisées de manière interchangeable. Afin de rendre tout cela plus clair, Git a introduit deux nouvelles commandes : switch et restore.

checkout est la plus confusante d’entre toutes tant elle a d’usages : changer de branche, annuler les changements sur un fichier dans la staging, placer HEAD sur un commit arbitraire, bref… Le but de checkout est de mettre à jour le répertoire de travail ou de changer de branches.

Pour que les choses soient plus claires, Git introduit donc switch, dont le seul but est de changer de branches – switch branches en anglais. Son nom et son utilité sont clairs comme de l’eau de roche.

En plus du changement de branches, checkout est également utilisé pour restaurer des fichiers dans l’espace de travail. Soit restaurer un fichier depuis un ancien commit, soit désindexer un fichier placé dans la staging, soit supprimer les modifications faites à un fichier et non commitées. Pour cela, on utilise aussi parfois reset, laquelle commande réinitialise HEAD à un état donné, mais dont le comportement change du tout au tout selon les options et paramètres passés.

En réalité, bien qu’en surface l’effet immédiat puisse sembler similaire, leur fonctionnement est assez différent. checkout change le pointeur de HEAD tandis que reset modifie le pointeur sur lequel est HEAD.

checkout et reset visualisés
Schéma montrant les différences entre reset et checkout tiré d'un fil StackOverflow

Cependant, il est possible de passer un ou plusieurs fichiers à reset. Or il n’est pas possible de remplacer HEAD partiellement. Soit le contenu de HEAD référence un commit, soit il en référence un autre, mais le fifty-fifty n’est pas possible. Donc lorsque reset reçoit un chemin en paramètre, le ou les fichiers sont restaurés dans l’index (mais pas dans l’espace de travail).

Comme tout cela est bien compliqué, Git introduit la commande restore pour ce second type d’actions. Cette dernière vise un seul et unique but : restaurer les fichiers de l’espace de travail. Elle possède néanmoins quelques options fort utiles permettant d’impacter la zone d’index.

Nous avons observé ces comportements dans le chapitre dédié à l’historique. Reprenons ces exemples et voyons les correspondances avec les “anciennes” commandes. Nous travaillons toujours avec le projet Jamments.

# Placer HEAD sur un point de commit arbitraire
git switch -d 7eb13be

# Équivalent avec checkout
git checkout 7eb13be

# Restaurer un fichier seul
# Sans --source, restore replace le fichier dans l'état de l'index ou de HEAD
git restore --source dfa88af tables.sql

# Pour obtenir un comportement semblable à la commande restore,
# il faut utiliser checkout (restaure à la fois l'index et le répertoire de travail)
# Avec restore ce serait git restore --staged --worktree --source dfa88af tables.sql
git checkout dfa88af tables.sql

# reset replace par défaut le fichier dans l'index uniquement
# Identique à git restore --staged --source dfa88af tables.sql
git reset dfa88af tables.sql

restore possède les options --staged et --worktree selon que l’on veuille affecter l’index ou le répertoire de travail. Le comportement par défaut concerne le répertoire de travail. Toutefois, si l’on veut affecter les deux en mêmes temps, il faudra passer les deux à la fois. Ces deux options possèdent respectivement les versions courtes -S et -W, le -s minuscule étant le raccourci de --source.

Dernier petit détail, comme par défaut restore restaure l’espace de travail à partir de l’index s’il est présent, ou de HEAD si rien n’est dans l’index. Effectuer l’inverse du git add demandera de passer l’option --staged. Par ailleurs, lorsqu’à la fois l’espace de travail et l’index sont modifiés et que l’on passe les deux options -W et -S en même temps, on devra spécifier qu’il faut prendre HEAD comme source.

# L'index et le répertoire portent des modifications
git status
On branch master
Your branch and 'origin/master' have diverged,
and have 4 and 10 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   README.md

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   README.md

# Pour restaurer le tout en une seule commande, on précise HEAD en source
git restore -W -S -s HEAD .

Commentaires

Rejoignez la discussion !

Vous pouvez utiliser Markdown pour les liens [ancre de lien](url), la mise en *italique* et en **gras**. Enfin pour le code, vous pouvez utiliser la syntaxe `inline` et la syntaxe bloc

```
ceci est un bloc
de code
```