git commit --amend modifie le dernier commit, git rebase -i
réorganise les N derniers commits, et git filter-repo nettoie tout
l’historique. Réécrire l’historique produit des commits propres et
logiques avant de les partager. Ce guide couvre les trois niveaux de
réécriture.
Prérequis : Rebase fondamental et Staging interactif.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Modifier le dernier commit avec
--amend(message ou contenu) - Réécrire plusieurs commits avec
rebase -i: squash, fixup, reword, edit, drop - Supprimer un fichier de tout l’historique avec
git filter-repo - Appliquer la règle d’or : ne jamais réécrire un historique déjà partagé
git commit --amend : modifier le dernier commit
Section intitulée « git commit --amend : modifier le dernier commit »La forme la plus simple de réécriture. Modifie le message et/ou le contenu du dernier commit :
Modifier le message
Section intitulée « Modifier le message »git commit --amend -m "fix: corriger le calcul de TVA"Ajouter des fichiers oubliés
Section intitulée « Ajouter des fichiers oubliés »git add fichier-oublie.pygit commit --amend --no-edit--no-edit conserve le message original. Le commit ammendé remplace
l’ancien (nouveau SHA).
Modifier l’auteur
Section intitulée « Modifier l’auteur »git commit --amend --author="Alice <alice@example.com>"git rebase -i : le couteau suisse
Section intitulée « git rebase -i : le couteau suisse »Le rebase interactif permet de réorganiser, fusionner, renommer, éditer ou supprimer une série de commits.
Lancer un rebase interactif
Section intitulée « Lancer un rebase interactif »# Réécrire les 5 derniers commitsgit rebase -i HEAD~5Git ouvre l’éditeur avec une liste de commits (du plus ancien au plus récent) :
pick a1b2c3d feat: ajouter le module pricingpick e4f5a6b fix: corriger la remisepick d7c8b9a wip: debugpick f0e1d2c feat: ajouter les testspick b3a4c5d fix: typo dans le READMELes commandes disponibles
Section intitulée « Les commandes disponibles »| Commande | Effet |
|---|---|
pick (p) | Garder le commit tel quel |
reword (r) | Garder le commit, modifier le message |
edit (e) | S’arrêter pour modifier le commit (contenu + message) |
squash (s) | Fusionner avec le commit précédent (combiner les messages) |
fixup (f) | Fusionner avec le précédent (supprimer le message du fixup) |
drop (d) | Supprimer le commit |
Vous pouvez aussi réordonner les lignes pour changer l’ordre des commits.
Exemple : nettoyer avant un push
Section intitulée « Exemple : nettoyer avant un push »Historique initial :
pick a1b2c3d feat: ajouter le module pricingpick e4f5a6b fix: corriger la remisepick d7c8b9a wip: debugpick f0e1d2c feat: ajouter les testspick b3a4c5d fix: typo dans le READMERéécriture souhaitée :
pick a1b2c3d feat: ajouter le module pricingfixup e4f5a6b fix: corriger la remisedrop d7c8b9a wip: debugpick f0e1d2c feat: ajouter les testsfixup b3a4c5d fix: typo dans le READMERésultat : 2 commits propres au lieu de 5.
Workflow rebase -i pas à pas
Section intitulée « Workflow rebase -i pas à pas »-
Vérifiez que vos commits ne sont pas encore poussés :
Fenêtre de terminal git log origin/main..HEAD --oneline -
Lancez le rebase interactif :
Fenêtre de terminal git rebase -i HEAD~5 -
Modifiez les commandes (
pick→squash,fixup,drop…) dans l’éditeur, sauvegardez, fermez. -
Si
squash: Git ouvre l’éditeur pour combiner les messages. Rédigez un message propre. -
Si conflit : résolvez puis continuez :
Fenêtre de terminal git add fichier-resolu.pygit rebase --continue -
Pour annuler à tout moment :
Fenêtre de terminal git rebase --abort
L’option edit en détail
Section intitulée « L’option edit en détail »edit stoppe le rebase pour vous laisser modifier un commit
intermédiaire :
# Le rebase s'arrête au commit marqué "edit"# Modifiez les fichiers...git add .git commit --amendgit rebase --continueVous pouvez même découper un commit en deux :
# Au point d'arrêt "edit"git reset HEAD~1 # Annuler le commit (garder les fichiers)git add partie-1.pygit commit -m "feat: partie 1"git add partie-2.pygit commit -m "feat: partie 2"git rebase --continue--autosquash : automatiser le fixup
Section intitulée « --autosquash : automatiser le fixup »Git peut placer automatiquement les commits de fixup au bon endroit :
# Créer un commit de fixup lié au commit a1b2c3dgit commit --fixup=a1b2c3d
# Lancer le rebase avec autosquashgit rebase -i --autosquash HEAD~10Le commit fixup! feat: ajouter le module pricing est automatiquement
placé juste après et marqué fixup.
Pour activer --autosquash par défaut :
git config --global rebase.autoSquash truegit filter-repo : nettoyage profond
Section intitulée « git filter-repo : nettoyage profond »Pour supprimer un fichier de tout l’historique (par exemple un
secret commité par erreur), git filter-repo remplace l’ancien
filter-branch (déprécié).
Checklist avant d’utiliser filter-repo
Section intitulée « Checklist avant d’utiliser filter-repo »- Le secret exposé est-il déjà changé/révoqué ? (sinon, faites-le d’abord)
- Tout le monde est-il prévenu et ses branches locales sauvegardées ?
- Avez-vous une sauvegarde du dépôt original (
git bundle create backup.bundle --all) ? - Le dépôt est-il clôné en « fresh clone » (ne pas l’exécuter sur un dépôt avec des modifications locales) ?
Installation
Section intitulée « Installation »# Via pippip install git-filter-repo
# Via le gestionnaire de paquets# Debian/Ubuntuapt install git-filter-repo# macOSbrew install git-filter-repoSupprimer un fichier de tout l’historique
Section intitulée « Supprimer un fichier de tout l’historique »git filter-repo --invert-paths --path secrets/api-key.txtCette commande réécrit chaque commit pour supprimer le fichier. Tous les SHA changent.
Remplacer du texte dans tout l’historique
Section intitulée « Remplacer du texte dans tout l’historique »Créez un fichier de remplacement :
regex:AKIA[A-Z0-9]{16}==>REDACTED_AWS_KEYliteral:mon-mot-de-passe==>REDACTEDgit filter-repo --replace-text replacements.txtBFG Repo Cleaner : alternative rapide
Section intitulée « BFG Repo Cleaner : alternative rapide »BFG est plus simple que filter-repo pour des cas courants :
# Installer (nécessite Java)# Télécharger depuis https://rtyley.github.io/bfg-repo-cleaner/
# Supprimer un fichier de tout l'historiquebfg --delete-files api-key.txt
# Supprimer les fichiers > 100 Mobfg --strip-blobs-bigger-than 100M
# Remplacer du textebfg --replace-text passwords.txt
# Nettoyer après BFGgit reflog expire --expire=now --allgit gc --prune=now --aggressiveComparatif des outils
Section intitulée « Comparatif des outils »| Outil | Portée | Cas d’usage | Complexité |
|---|---|---|---|
--amend | Dernier commit | Message ou contenu oublié | Faible |
rebase -i | N derniers commits | Squash, reword, réordonner | Moyenne |
filter-repo | Tout l’historique | Supprimer secrets/gros fichiers | Élevée |
| BFG | Tout l’historique | Supprimer fichiers/texte | Moyenne |
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
CONFLICT pendant rebase -i | Commits interdépendants réordonnés | Résolvez chaque conflit, git rebase --continue |
| Rebase boucle sur le même conflit | Commit conflictuel non résolu | git rebase --abort et repensez l’ordre |
Cannot rebase: You have unstaged changes | Working dir sale | git stash avant le rebase |
| filter-repo refuse de s’exécuter | N’est pas un clone « fresh » | Ajoutez --force ou clonez le repo d’abord |
push rejected après réécriture | SHA ont changé | git push --force-with-lease (jamais --force seul) |
À retenir
Section intitulée « À retenir »--amend: rapide pour le dernier commitrebase -i: squash, fixup, reword, edit, drop, réordonner--fixup+--autosquashautomatisent le nettoyagefilter-repo: pour les nettoyages profonds (secrets, gros fichiers)- Règle d’or : ne réécrivez jamais des commits déjà partagés
- Après réécriture :
--force-with-lease(pas--force)