Comment annuler et supprimer un commit Git spécifique de la branche actuelle

GitGitBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce laboratoire, vous apprendrez à gérer l'historique de vos commits Git. Vous pratiquerez l'annulation de modifications avec git reset, la réversion sécurisée de commits publics avec git revert, et la suppression de commits spécifiques de votre branche à l'aide d'un rebase interactif. Vous apprendrez également à utiliser le reflog pour récupérer des commits qui ont été supprimés. Ce sont des compétences essentielles pour maintenir un historique de projet propre et compréhensible.

Inspection de l'historique des commits

Avant de modifier l'historique, vous devez d'abord savoir comment le visualiser. La commande git log est l'outil principal pour cela. Pour ce laboratoire, un dépôt Git a été initialisé avec plusieurs commits afin de simuler un historique de projet réel.

Commençons par inspecter l'historique des commits. Nous utiliserons l'option --oneline pour afficher chaque commit sur une seule ligne et --graph pour afficher l'historique des commits sous forme de graphique, ce qui est utile pour visualiser les branches et les fusions (merges).

Exécutez la commande suivante dans votre terminal :

git log --oneline --graph

Vous devriez voir une liste des cinq commits qui ont été créés pour vous, le commit le plus récent étant en haut. Chaque ligne affiche un hash de commit unique (une version courte de celui-ci) et le message de commit.

* 7d3d24a (HEAD -> master) chore: Add last-commit file
* 8a9f1b3 docs: Update documentation in file1
* c2e4d6f fix: Add a temporary file that should be removed
* 5e1a3b2 feat: Add file2.txt
* 1b4c0a9 feat: Add file1.txt

Note : Vos hashes de commit seront différents de l'exemple ci-dessus. C'est normal, car chaque hash est unique.

Prenez un moment pour examiner l'historique. Vous manipulerez ces commits dans les étapes suivantes.

Annuler le dernier commit avec git reset

Parfois, vous effectuez un commit et vous réalisez immédiatement que vous avez fait une erreur. La commande git reset est parfaite pour ce scénario. Elle peut déplacer le pointeur HEAD de la branche actuelle vers un commit précédent, "annulant" ainsi un ou plusieurs commits.

Nous utiliserons l'option --soft, qui annule le commit mais laisse les modifications de ce commit dans votre zone de staging (l'index). C'est utile si vous souhaitez refaire le commit des modifications, peut-être avec un message différent ou combiné avec d'autres modifications.

Annulons le commit le plus récent, "chore: Add last-commit file".

git reset --soft HEAD~1

Ici, HEAD~1 fait référence au commit juste avant le HEAD actuel.

Maintenant, vérifiez le statut de votre dépôt :

git status

Vous verrez que last-commit.txt est maintenant listé sous "Changes to be committed" (Modifications à commiter). Cela signifie que le commit lui-même a été annulé, mais que les modifications du fichier sont toujours dans la zone de staging.

On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   last-commit.txt

Enfin, affichez à nouveau le log pour confirmer que le commit a disparu de l'historique :

git log --oneline --graph
* 8a9f1b3 (HEAD -> master) docs: Update documentation in file1
* c2e4d6f fix: Add a temporary file that should be removed
* 5e1a3b2 feat: Add file2.txt
* 1b4c0a9 feat: Add file1.txt

Comme vous pouvez le constater, le dernier commit a été supprimé du log, mais votre travail est en sécurité dans la zone de staging.

Annuler un commit avec git revert

Alors que git reset est excellent pour les modifications locales, il réécrit l'historique, ce qui peut poser problème si vous avez déjà partagé vos commits avec d'autres. Une manière plus sûre d'annuler des modifications sur une branche publique est git revert. Cette commande crée un nouveau commit qui applique l'inverse des modifications d'un commit spécifié.

Tout d'abord, nettoyons notre répertoire de travail en refaisant le commit des modifications de l'étape précédente.

git commit -m "chore: Add last-commit file again"

Maintenant, supposons que nous voulions annuler le commit qui a ajouté file2.txt. Ce commit est plus loin dans notre historique. Nous allons l'annuler (revert). Nous pouvons y faire référence par sa position relative par rapport à HEAD. En regardant le log de l'Étape 1, "feat: Add file2.txt" est le quatrième commit en partant du haut, nous pouvons donc y faire référence comme HEAD~3.

Exécutez la commande de revert :

git revert HEAD~3

Cela ouvrira votre éditeur de texte par défaut (vim par défaut) avec un message de commit pré-rempli comme "Revert 'feat: Add file2.txt'". Vous pouvez simplement enregistrer et fermer le fichier pour accepter le message par défaut.

Dans vim, tapez :wq et appuyez sur Entrée pour enregistrer et quitter.

Maintenant, vérifiez à nouveau le log :

git log --oneline --graph

Vous verrez un nouveau commit en haut, "Revert 'feat: Add file2.txt'".

* 1e2d3f4 (HEAD -> master) Revert "feat: Add file2.txt"
* 7d3d24a chore: Add last-commit file again
* 8a9f1b3 docs: Update documentation in file1
* c2e4d6f fix: Add a temporary file that should be removed
* 5e1a3b2 feat: Add file2.txt
* 1b4c0a9 feat: Add file1.txt

Le commit original est toujours dans l'historique, mais ses modifications ont été annulées par le nouveau commit de revert. Vous pouvez le vérifier en listant les fichiers dans le répertoire.

ls

Vous remarquerez que file2.txt n'est plus présent.

Supprimer un commit avec le rebase interactif

Pour une manipulation plus complexe de l'historique, comme la suppression d'un commit au milieu d'une branche, vous pouvez utiliser le rebase interactif (git rebase -i). C'est une commande très puissante qui réécrit l'historique des commits, elle doit donc être utilisée avec prudence, en particulier sur les branches partagées avec d'autres développeurs.

Notre objectif est de supprimer le commit avec le message "fix: Add a temporary file that should be removed". En regardant le log actuel, ce commit est maintenant HEAD~3.

Lancez le processus de rebase interactif :

git rebase -i HEAD~4

Cette commande ouvrira votre éditeur de texte (vim par défaut) avec une liste des 4 derniers commits.

pick fd5a181 fix: Add a temporary file that should be removed
pick 5f27a4d docs: Update documentation in file1
pick 284be6f chore: Add last-commit file again
pick 8a460c5 Revert "feat: Add file2.txt"

## Rebase 9403080..8a460c5 onto 9403080 (4 commands)
#
## Commands:
## p, pick <commit> = use commit
## d, drop <commit> = remove commit
## ...

Pour supprimer le commit, changez le mot pick en drop (ou d) pour la ligne contenant "fix: Add a temporary file that should be removed".

Changez ceci :

pick fd5a181 fix: Add a temporary file that should be removed

En ceci :

drop fd5a181 fix: Add a temporary file that should be removed

Dans vim, appuyez sur i pour entrer en mode insertion, effectuez vos modifications, puis appuyez sur Esc pour quitter le mode insertion. Enregistrez et quittez en tapant :wq et en appuyant sur Entrée. Git rejouera les commits restants sur la nouvelle histoire.

Vérifiez le log pour voir le résultat :

git log --oneline --graph

Le commit "indésirable" a maintenant disparu de l'historique.

* a5b4c3d (HEAD -> master) chore: Add last-commit file again
* f9e8d7c docs: Update documentation in file1
* 1e2d3f4 Revert "feat: Add file2.txt"
* 5e1a3b2 feat: Add file2.txt
* 1b4c0a9 feat: Add file1.txt

Vérifiez également les fichiers dans le répertoire. Le fichier bad-commit-file.txt a été supprimé.

ls

Restaurer un commit supprimé avec git reflog

Et si vous supprimiez un commit par erreur ? Git conserve un enregistrement de toutes les modifications apportées au pointeur HEAD dans un journal spécial appelé reflog. C'est votre filet de sécurité. Vous pouvez l'utiliser pour trouver et restaurer des commits perdus.

Visualisons le reflog pour trouver l'historique que nous venons de réécrire.

git reflog

Vous verrez une liste des actions que vous avez effectuées. Recherchez la ligne qui indique rebase (finish): returning to refs/heads/master. L'entrée juste en dessous, probablement HEAD@{1}, représente l'état de votre branche avant le rebase.

a5b4c3d (HEAD -> master) HEAD@{0}: rebase (finish): returning to refs/heads/master
1e2d3f4 HEAD@{1}: rebase (start): checkout HEAD~3
...

Nous pouvons restaurer notre branche à cet état précédent en utilisant git reset --hard. Cette commande est destructive et supprimera toutes les modifications non commitées, utilisez-la donc avec précaution.

Réinitialisons notre branche à l'état antérieur au rebase, qui est HEAD@{1} dans ce cas.

git reset --hard HEAD@{1}

Vous verrez un message confirmant que HEAD est maintenant au commit qui précédait le début du rebase.

HEAD is now at 1e2d3f4 Revert "feat: Add file2.txt"

Maintenant, vérifiez le log une dernière fois :

git log --oneline --graph

Vous devriez voir l'historique tel qu'il était avant le rebase :

* f461400 (HEAD -> master) Revert "feat: Add file2.txt"
* acea45c chore: Add last-commit file again
* c04b3f5 docs: Update documentation in file1
* 9403080 feat: Add file2.txt
* ee39412 feat: Add file1.txt

Notez que le commit "fix: Add a temporary file that should be removed" n'est toujours pas présent - c'est correct ! La commande git reset --hard HEAD@{1} nous a restaurés à l'état avant le début du rebase interactif, et non avant la suppression du commit. Le rebase interactif a réussi à supprimer ce commit indésirable de notre historique. Vous pouvez exécuter ls pour confirmer que bad-commit-file.txt n'est toujours pas présent. Le reflog est un outil inestimable pour récupérer après des erreurs dans Git.

Résumé

Dans ce laboratoire, vous avez appris des techniques pratiques pour gérer l'historique de vos commits Git. Vous avez commencé par inspecter l'historique avec git log. Vous avez ensuite pratiqué l'annulation de commits avec git reset --soft, la réversion sécurisée des modifications avec git revert, et la suppression de commits spécifiques avec la puissante commande git rebase -i. Enfin, vous avez appris à utiliser git reflog comme filet de sécurité pour restaurer les commits qui ont été supprimés de l'historique. Ces compétences sont essentielles pour maintenir un historique de projet propre et gérable.