Retour vers le commit
Dans le précédent atelier pratique, nous avons vu en détail le rôle de la
référence HEAD. Aujourd'hui nous allons voir ensemble ce que vous pouvez
faire si vous souhaitez supprimer ou autrement défaire un commit avec Git. Ce
sera l'occasion de mettre en pratique ce que nous avons appris sur HEAD.
Plutôt soft ou hard ?
Faisons une petite démonstration pratique avec le dépôt Git atelier-18.
Effectuez une nouvelle copie de travail de ce dépôt :
Affichons sommairement son historique :
$ git log --oneline
cbeca14 (HEAD -> master) Ajout du fichier Cartes
7def037 Ajout d'une destination
9159976 Ajout du fichier Entretien
4220c4c Ajout du fichier Roadtrip
D'après les logs, le dernier commit a ajouté un fichier au dépôt. Voyons ce que cela a donné en détail :
$ git diff HEAD~1 HEAD
diff --git a/Cartes.md b/Cartes.md
new file mode 100644
index 0000000..a6e35b6
--- /dev/null
+++ b/Cartes.md
@@ -0,0 +1,9 @@
+# Cartes routières
+
+- [ ] France
+
+- [ ] Italie
+
+- [ ] Suisse
+
+- [ ] Autriche
À ce stade, vous vous dites que réflexion faite, ce n'est pas la peine
d'établir une liste de cartes routières, puisque vous disposez d'un GPS avec
des cartes pour toute l'Europe. Le fichier Cartes.md est donc inutile, tout
comme le dernier commit qui l'a ajouté au dépôt. Est-ce qu'il n'y aurait pas
moyen de supprimer ce dernier commit et le fichier qui va avec ?
Oui, avec la commande git reset, qui permet de déplacer la référence HEAD.
Un reset peut fonctionner de trois manières :
-
soft
-
mixed
-
hard
Voyons par la pratique ce que cela donne et commençons par la méthode douce :
Examinons le résultat de cette opération :
$ git log --oneline
7def037 (HEAD -> master) Ajout d'une destination
9159976 Ajout du fichier Entretien
4220c4c Ajout du fichier Roadtrip
$ ls
Cartes.md Entretien.md Roadtrip.md
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: Cartes.md
Voici en gros ce qui s'est passé :
-
Le dernier commit a été supprimé.
-
Plus exactement,
HEADa été déplacé versHEAD~1. -
Le fichier
Cartes.mda été placé dans l'index. -
On en trouve une copie dans le répertoire de travail.
Si jamais je change d'avis, je peux donc rétablir l'état de mon dépôt comme ceci :
$ git commit -m "Ajout du fichier Cartes"
[master 591f650] Ajout du fichier Cartes
1 file changed, 9 insertions(+)
create mode 100644 Cartes.md
$ git log --oneline
591f650 (HEAD -> master) Ajout du fichier Cartes
7def037 Ajout d'une destination
9159976 Ajout du fichier Entretien
4220c4c Ajout du fichier Roadtrip
Comment se passent les choses si j'effectue un reset en mode mixed ?
Essayons :
$ git reset --mixed HEAD~1
$ git log --oneline
7def037 (HEAD -> master) Ajout d'une destination
9159976 Ajout du fichier Entretien
4220c4c Ajout du fichier Roadtrip
$ ls
Cartes.md Entretien.md Roadtrip.md
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
Cartes.md
nothing added to commit but untracked files present (use "git add" to track)
-
Le dernier commit a disparu.
-
Cette fois-ci, le fichier
Cartes.mdn'a pas été copié dans l'index. -
En revanche, il est toujours présent dans le répertoire de travail.
Si je veux annuler l'opération de suppression du commit, je peux toujours faire marche arrière comme ceci :
$ git add Cartes.md
$ git commit -m "Ajout du fichier Cartes"
[master 51ac9f6] Ajout du fichier Cartes
1 file changed, 9 insertions(+)
create mode 100644 Cartes.md
$ git log --oneline
51ac9f6 (HEAD -> master) Ajout du fichier Cartes
7def037 Ajout d'une destination
9159976 Ajout du fichier Entretien
4220c4c Ajout du fichier Roadtrip
Il ne nous reste plus qu'à inspecter le fonctionnement du mode hard :
$ git reset --hard HEAD~1
HEAD is now at 7def037 Ajout d'une destination
$ git log --oneline
7def037 (HEAD -> master) Ajout d'une destination
9159976 Ajout du fichier Entretien
4220c4c Ajout du fichier Roadtrip
$ ls
Entretien.md Roadtrip.md
$ git status
On branch master
nothing to commit, working tree clean
-
Le dernier commit a disparu des logs.
-
Le fichier
Cartes.mda également été envoyé au paradis des octets. On ne le trouve plus ni dans l'index, ni dans le répertoire de travail.
Deux remarques sur ces différentes façons d'effectuer un reset :
-
Le mode mixed est utilisé par défaut :
git reset HEAD~1équivaut àgit reset --mixed HEAD~1. -
Contrairement aux modes soft et mixed, le mode hard est un mode destructif.
Défaire un commit
Il existe une autre façon de revenir sur ses pas et détricoter ce qu'on vient
de faire, c'est la commande git revert. Là encore, un exemple pratique vous
permettra de mieux comprendre. Effectuez une nouvelle copie de travail du dépôt
Git atelier-18 :
C'est toujours le même dépôt que dans l'exemple ci-dessus :
$ git log --oneline
cbeca14 (HEAD -> master) Ajout du fichier Cartes
7def037 Ajout d'une destination
9159976 Ajout du fichier Entretien
4220c4c Ajout du fichier Roadtrip
Tout à l'heure nous avons invoqué git diff pour savoir en quoi consistait
exactement ce dernier commit :
$ git diff HEAD~1 HEAD
diff --git a/Cartes.md b/Cartes.md
new file mode 100644
index 0000000..a6e35b6
--- /dev/null
+++ b/Cartes.md
@@ -0,0 +1,9 @@
+# Cartes routières
+
+- [ ] France
+
+- [ ] Italie
+
+- [ ] Suisse
+
+- [ ] Autriche
Si je souhaite faire marche arrière, j'ai le choix :
-
Je peux supprimer le commit grâce à
git reset, comme nous venons de le voir. -
Alternativement, je peux faire une sorte de commit inversé grâce à la commande
git revert.
Voyons ce que cela donne dans la pratique :
Cette opération ouvre l'éditeur par défaut avec un message de commit :
Je garde le message de commit tel quel et je l'enregistre :
Removing Cartes.md
[master 301909d] Revert "Ajout du fichier Cartes"
1 file changed, 9 deletions(-)
delete mode 100644 Cartes.md
L'opération s'est soldée par un nouveau commit :
$ git log --oneline
301909d (HEAD -> master) Revert "Ajout du fichier Cartes"
cbeca14 Ajout du fichier Cartes
7def037 Ajout d'une destination
9159976 Ajout du fichier Entretien
4220c4c Ajout du fichier Roadtrip
Maintenant, si j'effectue un git diff pour voir la différence entre les deux
précédents commits, je m'aperçois qu'ils sont exactement opposés :
$ git diff HEAD~2 HEAD~1
diff --git a/Cartes.md b/Cartes.md
new file mode 100644
index 0000000..a6e35b6
--- /dev/null
+++ b/Cartes.md
@@ -0,0 +1,9 @@
+# Cartes routières
+
+- [ ] France
+
+- [ ] Italie
+
+- [ ] Suisse
+
+- [ ] Autriche
$ git diff HEAD~1 HEAD
diff --git a/Cartes.md b/Cartes.md
deleted file mode 100644
index a6e35b6..0000000
--- a/Cartes.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Cartes routières
-
-- [ ] France
-
-- [ ] Italie
-
-- [ ] Suisse
-
-- [ ] Autriche
Attention à la syntaxe
Notez la différence cruciale dans la syntaxe :
-
Lorsque vous écrivez
git revert HEAD, vous écrivez en argument l'ID du commit que vous souhaitez défaire. -
Avec
git reset HEAD~1, vous fournissez l'ID du commit vers lequel vous souhaitez revenir.
Vous voilà donc confronté à un choix : utiliser reset ou revert ?
À vous de voir si vous préférez réécrire l'histoire ou garder une trace de vos
errances.
Éditer un message de commit
Il nous reste à voir un dernier cas de figure. Il peut arriver que l'on effectue un commit avec un message pas assez explicite ou autrement inapproprié. Et après coup on se dit qu'on aurait pu faire mieux. Dans ce cas, Git nous permet de rectifier le tir.
Revenez dans le dépôt Git atelier-26 et affichez les logs :
$ cd ../atelier-26
$ git log --oneline
7def037 (HEAD -> master) Ajout d'une destination
9159976 Ajout du fichier Entretien
4220c4c Ajout du fichier Roadtrip
Le message de mon dernier commit dit Ajout d'une destination. Admettons que j'aurais préféré écrire Ajout d'une étape. Dans ce cas, je peux faire ceci :
$ git commit --amend -m "Ajout d'une étape"
[master 2393db1] Ajout d'une étape
Date: Tue Jan 31 07:56:14 2023 +0100
1 file changed, 2 insertions(+)
Ici j'ai rectifié le tir avec un nouveau commit au contenu identique mais avec un message différent :
$ git log --oneline
2393db1 (HEAD -> master) Ajout d'une étape
9159976 Ajout du fichier Entretien
4220c4c Ajout du fichier Roadtrip
Limites de l'option --amend
Gardez à l'esprit que cette fonctionnalité est limitée au dernier commit en cours. Elle ne vous permettra pas d'éditer des messages de commits antérieurs.
À vous de jouer !
-
Effectuez trois copies du dépôt Git
atelier-12et nommez-les respectivementatelier-28,atelier-29etatelier-30. -
Inspectez sommairement le contenu et l'historique du dépôt
atelier-28. -
Essayez de savoir en quoi consistait le dernier commit sur la branche
hello-cow. -
Supprimez ce commit en mode soft.
-
Changez d'avis et revenez en arrière.
-
Supprimez le dernier commit en mode mixed.
-
Changez d'avis et revenez en arrière.
-
Supprimez le dernier commit en mode hard.
-
Changez d'avis et... rendez-vous compte en grinçant des dents qu'il est trop tard pour changer d'avis.
-
Placez-vous à la racine du dépôt Git dans le répertoire
atelier-29. -
Défaites le dernier commit de la branche
hello-cowen gardant une trace de ce détricotage. -
Affichez le détail des deux derniers commits et comparez-les.
-
Placez-vous à la racine du dépôt Git dans le répertoire
atelier-30. -
Affichez les logs du dépôt.
-
Remplacez le message du dernier commit sur la branche
hello-cowpar Afficher une vache fatiguée.
La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce site ? Offrez un café au rédacteur en cliquant sur la tasse.

