GitRéécrire l'historique

Modifier le dernier commit

Ajouter un commit:

echo 'foo' > file1
git add .
git commit -m 'feat: add file'
git log --oneline

Supposons maintenant qu’on souhaite ajouter un autre fichier dans ce dernier commit:

echo 'bar' > file2

Pour modifier le dernier commit on peut ajouter les changements à l’index et utiliser le flag --amend:

git add file2
git commit --amend

Un éditeur va s’ouvrir pour vous demander de confirmer ou modifier les informations du commit que vous êtes en train de modifier.
Si vous ne souhaitez pas éditer le nom du commit vous pouvez simplement ajouter le flag --no-edit.

Utiliser un commit fixup

Le commit fixup est utile lorsque vous souhaitez corriger un commit précédent sans modifier son message. Cela permet de maintenir un historique clair, tout en appliquant les corrections avec un rebase interactif.

Créer plusieurs commits

Commençons par créer plusieurs commits pour avoir un historique de travail.

echo 'foo' > foo
git add foo
git commit -m 'feat: add foo file'
echo 'baz' > baz
git add baz
git commit -m 'feat: add baz file'
git log --oneline

Admettons que l’historique ressemble à cela :

d2f5b32 (HEAD -> main) feat: add baz file
a1c3e6f feat: add foo file

Ajouter une correction avec fixup

Vous vous rendez compte que vous avez oublié d’ajouter un fichier dans le commit a1c3e6f où vous avez introduit foo.
Pour corriger cela, vous allez utiliser commit —fixup en vous basant sur le hash du commit à corriger :

echo 'bar' > foo2
git add foo2
git commit --fixup a1c3e6f

Réécrire l’historique avec rebase interactif

Maintenant, il faut fusionner le commit de correction avec le commit original en utilisant un rebase interactif. Vous devez utiliser l’option —autosquash pour que fixup se positionne automatiquement :

git rebase -i --autosquash a1c3e6f~

Lorsque l’éditeur s’ouvre, vous verrez quelque chose comme ceci :

pick a1c3e6f feat: add foo file
fixup 82c4f23 fixup! feat: add foo file
pick d2f5b32 feat: add baz file

Vérifiez que la ligne fixup! est bien placée après le commit qu’elle corrige. Ensuite, sauvegardez et fermez l’éditeur.

Le rebase fusionnera le commit fixup avec le commit original a1c3e6f, tout en laissant le reste de l’historique intact.

Résultat après rebase

Après le rebase, votre historique sera propre et le commit fixup aura disparu :

git log --oneline
d2f5b32 feat: add baz file
a1c3e6f feat: add foo file

Les modifications de file2 auront été incluses dans le commit original a1c3e6f.

Utiliser git stash avec un rebase interactif

Créer plusieurs commits

Commençons par créer plusieurs commits pour établir un historique de travail.

echo 'foo' > file1
git add file1
git commit -m 'feat: add foo file'
echo 'baz' > file3
git add file3
git commit -m 'feat: add baz file'
git log --oneline

Admettons que l’historique ressemble à ceci :

d2f5b32 (HEAD -> main) feat: add baz file
a1c3e6f feat: add foo file

Apporter des modifications et les stasher

Vous réalisez maintenant que vous devez modifier le commit a1c3e6f (celui avec foo). Plutôt que d’ajouter les modifications à l’index directement, vous les stasherez :

echo 'bar' > file2
git stash

Cela stocke vos modifications localement sans les inclure dans le dernier commit ni les ajouter à l’index.

Lancer un rebase interactif

Maintenant, vous allez lancer un rebase interactif pour éditer le commit a1c3e6f :

git rebase -i a1c3e6f~

Lorsque l’éditeur s’ouvre, changez l’instruction de pick à edit pour le commit que vous souhaitez modifier (dans ce cas, a1c3e6f).

edit a1c3e6f feat: add foo file
pick d2f5b32 feat: add baz file

Sauvegardez et fermez l’éditeur.

Appliquer les modifications via git stash pop

Le rebase s’arrêtera sur le commit que vous avez choisi d’éditer (a1c3e6f). À ce stade, vous pouvez récupérer les modifications stachées :

git stash pop

Cela appliquera les modifications que vous aviez stachées (dans ce cas, l’ajout de file2).

Ajouter les modifications au commit et continuer le rebase

Maintenant, ajoutez les changements au commit existant :

git add file2
git rebase --continue

Vérifier l’historique après le rebase

Une fois que vous avez terminé le rebase, vérifiez que l’historique est correct et que les changements sont bien inclus dans le commit a1c3e6f :

git log --oneline

L’historique devrait être propre et ressembler à ceci :

d2f5b32 feat: add baz file
a1c3e6f feat: add foo file 

squash

Le squash permet de combiner plusieurs commits en un seul, ce qui est utile pour regrouper des modifications similaires (comme plusieurs corrections ou de la documentation) et garder un historique plus propre.

Le réordonnancement permet de modifier l’ordre des commits pour une meilleure lisibilité ou une cohérence logique.

Imaginons que votre historique ressemble à ceci :

a1c3e6f feat: add foo file
d2f5b32 feat: add baz file
45f133bd docs: add documentation for foo
e31c02dd docs: add additional documentation
f8ee1aef fix: correct typo in foo file
e8dc5c64 fix: add error handling in foo file

Dans cet exemple, nous allons :

  • Squasher les commits de documentation (docs) en un seul commit.
  • Regrouper les commits de correction (fix) avec le commit initial feat: add foo file.
  • Lancer un rebase interactif

Lancez un rebase interactif depuis un commit parent de votre branche

git rebase -i <hash-du-commit>~

Un éditeur de texte va s’ouvrir avec la liste de vos commits, dans un ordre descendant (du plus ancien au plus récent).

pick a1c3e6f feat: add foo file
pick d2f5b32 feat: add baz file
pick 45f133bd docs: add documentation for foo
pick e31c02dd docs: add additional documentation
pick f8ee1aef fix: correct typo in foo file
pick e8dc5c64 fix: add error handling in foo file

Squasher des Commits

Pour combiner plusieurs commits en un seul, remplacez pick par squash ou s pour les commits que vous voulez fusionner. Par exemple, pour fusionner les commits docs en un seul :

pick a1c3e6f feat: add foo file
pick d2f5b32 feat: add baz file
squash 45f133bd docs: add documentation for foo
squash e31c02dd docs: add additional documentation
pick f8ee1aef fix: correct typo in foo file
squash e8dc5c64 fix: add error handling in foo file

Réordonner des commits

Pour réordonner, déplacez les lignes dans l’ordre souhaité. Par exemple, si vous souhaitez que le commit feat: add baz file apparaisse après les corrections fix, réorganisez les lignes ainsi :

pick a1c3e6f feat: add foo file
squash f8ee1aef fix: correct typo in foo file
squash e8dc5c64 fix: add error handling in foo file
pick 45f133bd docs: add documentation for foo
squash e31c02dd docs: add additional documentation
pick d2f5b32 feat: add baz file

Confirmer et finaliser le rebase.

Sauvegardez et fermez l’éditeur pour appliquer le rebase. Si des conflits apparaissent, résolvez-les en suivant les instructions de Git, puis continuez le rebase avec :

git rebase --continue

Une fois terminé, vérifiez l’historique pour vous assurer que les commits sont bien organisés et combinés comme prévu :

git log --oneline

L’historique devrait être propre, avec les commits docs regroupés en un seul, les corrections fix fusionnées avec le commit feat: add foo file, et le commit feat: add baz file en dernier.

a1c3e6f feat: add foo file (includes fixes)
45f133bd docs: add documentation for foo
d2f5b32 feat: add baz file

Exercice

C’est parti!