Historique et annulation des modifications
L’historique de Git ne sert à rien si vous ne savez pas le lire et y revenir. Ce qui a changé et quand, comment abandonner une modification ratée, corriger le dernier commit et annuler une modification erronée – et comment sauver votre travail quand une annulation tourne mal.
Nous reprenons l’article Premier dépôt et premier commit : le dépôt du site d’exemple du café compte deux commits et nous travaillons dans le dossier web.
Ce qui a changé : git diff
Ajoutez dans la feuille de style un interligne pour les paragraphes :
Fichier css/style.css :
body { font-family: sans-serif; max-width: 40rem; margin: 0 auto; }
h1 { color: #6b3e26; }
p { line-height: 1.5; }
La commande git diff compare les fichiers du dossier avec l’index : elle affiche les modifications qui n’ont pas encore été préparées pour l’enregistrement :
git diff
diff --git a/css/style.css b/css/style.css
index 9d6b1d8..0a9b2bf 100644
--- a/css/style.css
+++ b/css/style.css
@@ -1,2 +1,3 @@
body { font-family: sans-serif; max-width: 40rem; margin: 0 auto; }
h1 { color: #6b3e26; }
+p { line-height: 1.5; }
Les lignes commençant par + ont été ajoutées, celles commençant par - supprimées (une ligne modifiée apparaît toujours comme une ligne supprimée et une nouvelle). Le fragment @@ -1,2 +1,3 @@ indique où se trouve la modification dans le fichier : les lignes d’origine 1 à 2 sont devenues les nouvelles lignes 1 à 3. Après git add, la commande git diff n’affiche plus rien ; les modifications préparées n’apparaissent qu’avec l’option --staged :
git add css/style.css git diff git diff --staged
diff --git a/css/style.css b/css/style.css
index 9d6b1d8..0a9b2bf 100644
--- a/css/style.css
+++ b/css/style.css
@@ -1,2 +1,3 @@
body { font-family: sans-serif; max-width: 40rem; margin: 0 auto; }
h1 { color: #6b3e26; }
+p { line-height: 1.5; }
git commit -m "Interligne plus grand"
[main bc90e17] Interligne plus grand 1 file changed, 1 insertion(+)
Désigner les commits : HEAD
Vous désignez un commit par son hash (le début suffit) ou de façon relative. HEAD est le commit sur lequel vous vous trouvez, en général le dernier commit de la branche courante. HEAD~1 est le commit qui le précède, HEAD~2 un commit encore plus ancien, et ainsi de suite. Les exemples utilisent la notation relative, car les hashes sont différents chez chacun :
git log --oneline
bc90e17 (HEAD -> main) Interligne plus grand 2b77571 Horaires prolongés fdafb87 Première version du site
Un commit et ses modifications s’affichent avec git show :
git show HEAD~1
commit 2b775713150150dddfd1c85aeb8be3cabd4eefe4
Author: Jean Dupont <jean.dupont@example.com>
Date: Tue Oct 13 09:07:00 2026 +0200
Horaires prolongés
diff --git a/index.php b/index.php
index b75aca2..441f50d 100644
--- a/index.php
+++ b/index.php
@@ -10,6 +10,6 @@ $title = "Café des Tilleuls";
</head>
<body>
<h1><?= htmlspecialchars($title) ?></h1>
- <p>Ouvert tous les jours de 8 h à 18 h.</p>
+ <p>Ouvert tous les jours de 8 h à 20 h.</p>
</body>
</html>
Pour afficher l’historique d’un seul fichier, indiquez son chemin après deux tirets. Les deux tirets séparent les chemins de fichiers des autres paramètres, pour que Git ne confonde pas un nom de fichier avec un nom de branche :
git log --oneline -- css/style.css
bc90e17 (HEAD -> main) Interligne plus grand fdafb87 Première version du site
Qui a modifié une ligne précise en dernier, et quand, vous l’apprenez avec la commande git blame. L’option -L limite la liste aux lignes indiquées (ici uniquement la ligne 13) :
git blame -L 13,13 index.php
2b775713 (Jean Dupont 2026-10-13 09:07:00 +0200 13) <p>Ouvert tous les jours de 8 h à 20 h.</p>
Abandonner une modification inachevée : git restore
Pendant que vous modifiez index.php, le titre disparaît par erreur et vous ne voulez pas le réécrire :
<?php $title = "Café des Tilleuls"; ?> <!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title><?= htmlspecialchars($title) ?></title> <link rel="stylesheet" href="css/style.css"> </head> <body> <p>Ouvert tous les jours de 8 h à 20 h.</p> </body> </html>
Liste d’état courte (-s, un fichier par ligne ; M dans la deuxième colonne = fichier modifié qui n’est pas dans l’index) et restauration du fichier dans l’état du dernier commit :
git status -s
M index.php
git restore index.php git status
On branch main nothing to commit, working tree clean
Attention : git restore écrase définitivement les modifications du dossier. Les modifications qui n’ont jamais été enregistrées dans un commit, Git ne les connaît pas et ne peut pas les récupérer.
Si une modification s’est retrouvée dans l’index par erreur, git restore --staged la retire de l’index et laisse le fichier du dossier tel quel :
body { font-family: sans-serif; max-width: 40rem; margin: 0 auto; }
h1 { color: #6b3e26; }
p { line-height: 1.5; }
h1 { font-size: 3rem; }
git add css/style.css git status -s git restore --staged css/style.css git status -s
M css/style.css M css/style.css
Dans la première liste, M se trouve dans la première colonne (modification dans l’index), dans la seconde, déjà dans la deuxième colonne (modification uniquement dans le dossier). Abandonnez maintenant la modification de la feuille de style, elle ne servira pas dans les exemples suivants :
git restore css/style.css
Corriger le dernier commit : --amend
Vous ajoutez une page de contact, mais le message du commit contient une faute de frappe :
Fichier contact.php :
<h1>Contact</h1> <p>Café des Tilleuls, 12 rue des Tilleuls, Lyon</p>
git add contact.php git commit -m "Page de cotnact"
[main c9be148] Page de cotnact 1 file changed, 2 insertions(+) create mode 100644 contact.php
L’option --amend remplace le dernier commit par un nouveau avec le message corrigé. Vous ajoutez de la même façon un fichier oublié : ajoutez-le avec git add et lancez git commit --amend --no-edit (--no-edit = garder le message) :
git commit --amend -m "Page de contact"
[main d43cd58] Page de contact Date: Tue Oct 13 09:26:00 2026 +0200 1 file changed, 2 insertions(+) create mode 100644 contact.php
La ligne Date correspond à l’heure de l’auteur : le commit corrigé la reprend du commit d’origine. Il a pourtant un nouveau hash : c’est un autre commit, et celui d’origine a disparu de l’historique de la branche. C’est pourquoi il ne faut pas corriger les commits qui se trouvent déjà dans un dépôt partagé (voir Dépôt distant : GitHub et GitLab). Les autres ont la version d’origine dans leur historique, et leur historique différerait du vôtre.
Annuler un ancien commit : git revert
L’interligne plus grand ne plaît pas et vous voulez l’annuler. git revert ne réécrit pas l’historique : il crée un nouveau commit qui inverse les modifications du commit indiqué. Vous pouvez ainsi annuler sans risque un commit que d’autres ont déjà. Sans l’option --no-edit, un éditeur s’ouvrirait avec un message préparé :
git revert --no-edit HEAD~1
[main e4b6e71] Revert "Interligne plus grand" Date: Tue Oct 13 09:28:00 2026 +0200 1 file changed, 1 deletion(-)
Le nouveau commit a reçu le message Revert "…", et le commit annulé est lui aussi resté dans l’historique :
git log --oneline
e4b6e71 (HEAD -> main) Revert "Interligne plus grand" d43cd58 Page de contact bc90e17 Interligne plus grand 2b77571 Horaires prolongés fdafb87 Première version du site
Si l’annulation rencontre des modifications ultérieures des mêmes lignes, Git signale un conflit, qui se résout de la même manière que lors de la fusion de branches, voir Branches et fusion.
Revenir d’un commit en arrière : git reset
git reset déplace la branche courante sur un autre commit : les commits plus récents en disparaissent. Selon l’option, les modifications des commits supprimés vont à un endroit différent :
- --soft : les modifications restent dans l’index, un nouveau git commit suffit (par exemple quand vous voulez réunir deux commits en un seul) ;
- --mixed (par défaut, sans option) : les modifications restent dans le dossier, mais pas dans l’index ;
- --hard : les modifications sont abandonnées et les fichiers du dossier sont écrasés selon le commit cible. Les modifications non enregistrées du dossier sont perdues elles aussi.
Vous changez d’avis sur l’annulation de l’interligne et voulez supprimer le commit de revert, comme s’il n’avait jamais existé :
git reset --soft HEAD~1 git status -s
M css/style.css
La modification du revert est restée dans l’index. Vous l’abandonnez avec git reset --hard sans commit : la commande ramène le dossier et l’index à l’état du dernier commit :
git reset --hard
HEAD is now at d43cd58 Page de contact
Comme --amend, la commande git reset réécrit l’historique ; utilisez-la donc uniquement pour des commits qui n’ont encore été envoyés nulle part. Pour les commits envoyés, utilisez git revert.
Récupérer après un reset : git reflog
Un autre reset supprime par erreur le commit de la page de contact :
git reset --hard HEAD~1
HEAD is now at bc90e17 Interligne plus grand
Le commit a disparu de l’historique de la branche, mais il est toujours dans le dépôt. Git note chaque déplacement de HEAD dans le reflog : commits, resets, changements de branche :
git reflog
bc90e17 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
d43cd58 HEAD@{1}: reset: moving to HEAD
d43cd58 HEAD@{2}: reset: moving to HEAD~1
e4b6e71 HEAD@{3}: revert: Revert "Interligne plus grand"
d43cd58 HEAD@{4}: commit (amend): Page de contact
c9be148 HEAD@{5}: commit: Page de cotnact
bc90e17 (HEAD -> main) HEAD@{6}: commit: Interligne plus grand
2b77571 HEAD@{7}: commit: Horaires prolongés
fdafb87 HEAD@{8}: commit (initial): Première version du site
HEAD@{1} est l’état avant le dernier déplacement, c’est-à-dire le commit de la page de contact. Vous y revenez avec un nouveau reset :
git reset --hard HEAD@{1}
git log --oneline
HEAD is now at d43cd58 Page de contact d43cd58 (HEAD -> main) Page de contact bc90e17 Interligne plus grand 2b77571 Horaires prolongés fdafb87 Première version du site
Par défaut, Git conserve les entrées du reflog pendant 90 jours (30 jours pour les commits qui n’appartiennent plus à aucune branche), puis les supprime lors du nettoyage du dépôt. Le reflog n’existe que dans votre dépôt, il n’est pas envoyé au dépôt distant. Dans PowerShell, mettez HEAD@{1} entre guillemets, car les accolades y ont un autre sens.
Ancienne version d’un fichier
Vous ne voulez pas annuler tout un commit, vous avez seulement besoin d’index.php dans l’état du premier commit. L’option --source de la commande git restore récupère un fichier depuis n’importe quel commit :
git restore --source=HEAD~3 index.php git diff
diff --git a/index.php b/index.php index 441f50d..b75aca2 100644 --- a/index.php +++ b/index.php @@ -10,6 +10,6 @@ $title = "Café des Tilleuls"; </head> <body> <h1><?= htmlspecialchars($title) ?></h1> - <p>Ouvert tous les jours de 8 h à 20 h.</p> + <p>Ouvert tous les jours de 8 h à 18 h.</p> </body> </html>
Le fichier se trouve maintenant dans le dossier sous sa forme d’origine : vous pouvez l’enregistrer dans un nouveau commit ou le restaurer avec la même commande sans --source. Vous pouvez aussi simplement afficher le contenu d’un fichier d’un autre commit, sans rien écraser : git show HEAD~3:index.php.