Un historique Git propre est un atout professionnel majeur. Ce module couvre les outils de réécriture d'historique : rebase, cherry-pick, reset et le filet de sécurité reflog.
1 · git rebase
git rebase déplace les commits d'une branche en les "rejouant" sur un nouveau commit de base.
Contrairement au merge, il produit un historique linéaire sans commit de fusion parasite.
Merge vs Rebase
Avec merge — historique non linéaire
Avec rebase — historique linéaire
Commande de base
# Se placer sur la branche feature
git switch feature/login
# Rejouer les commits de feature sur main
git rebase main
# Ensuite fast-forward merge sur main
git switch main
git merge --ff-only feature/login
Résoudre les conflits pendant un rebase
# Git s'arrête sur chaque commit conflictuel
# 1. Résoudre manuellement les fichiers
git add fichier-resolu.txt
# 2. Continuer le rebase
git rebase --continue
# Ou annuler et revenir à l'état initial
git rebase --abort
2 · Rebase interactif
Le rebase interactif (-i) ouvre un éditeur listant les commits à rejouer.
On peut réordonner, fusionner, modifier, ou supprimer des commits.
Lancer un rebase interactif
# Modifier les 3 derniers commits
git rebase -i HEAD~3
# Modifier depuis un commit précis
git rebase -i abc1234^
Liste des commandes disponibles
pickp — Garder le commit tel quel (action par défaut)rewordr — Garder le commit mais modifier son messageedite — Arrêter pour modifier le contenu du commitsquashs — Fusionner avec le commit précédent, concaténer les messagesfixupf — Fusionner avec le précédent, ignorer ce messagedropd — Supprimer le commit entièrement
Exemple : squasher 3 commits en 1
# Fichier ouvert par git rebase -i HEAD~3
pick a1b2c3 feat: ajout formulaire login
s d4e5f6 fix: correction validation email
s g7h8i9 style: mise en forme bouton submit
# → Git ouvrira un second éditeur pour le message final combiné
# Résultat : 1 seul commit "feat: ajout formulaire login complet"
Exemple : reword pour corriger un message
# Fichier de rebase interactif
pick a1b2c3 feat: add login form
r d4e5f6 fix typo ← "r" au lieu de "pick"
pick g7h8i9 docs: mise à jour README
# Git va s'arrêter sur d4e5f6 pour vous laisser changer le message
force-push sera nécessaire — ce qui impacte les collaborateurs.
3 · git cherry-pick
git cherry-pick applique un commit spécifique (identifié par son hash) sur la branche courante,
sans fusionner toute la branche source. Idéal pour backporter un correctif.
Appliquer un commit précis
# Récupérer le hash du commit à appliquer
git log --oneline feature/login
# → abc1234 fix: correction faille XSS dans le formulaire
# Appliquer ce seul commit sur main
git switch main
git cherry-pick abc1234
Cherry-pick d'une plage de commits
# Appliquer les commits de abc1234 jusqu'à def5678 (inclus)
git cherry-pick abc1234^..def5678
# Options utiles
git cherry-pick -n abc1234 # --no-commit : stager sans committer
git cherry-pick -x abc1234 # Ajouter la référence source dans le message
Cas d'usage typique : hotfix backport
# Un correctif urgent a été fait sur develop
# On doit l'appliquer sur la branche release/v2.0 sans merger develop entier
git switch release/v2.0
git cherry-pick f1a2b3c # le hash du correctif
git push origin release/v2.0
git log --all --oneline --graph pour visualiser les commits de toutes les branches et retrouver le hash exact à cherry-picker.
4 · git reset
git reset déplace le pointeur HEAD (et la branche courante) vers un commit antérieur.
Le comportement sur les fichiers dépend du mode utilisé.
Les 3 modes de reset
| Mode | Commande | Index (staging) | Working directory |
|---|---|---|---|
| --soft | git reset --soft HEAD~1 |
Inchangé (fichiers stagés) | Inchangé |
| --mixed | git reset HEAD~1 (défaut) |
Vidé (unstaged) | Inchangé |
| --hard | git reset --hard HEAD~1 |
Vidé | Effacé ⚠ |
Exemples pratiques
# --soft : défaire le dernier commit mais garder les changements stagés
git reset --soft HEAD~1
# → Les fichiers restent dans "Changes to be committed"
# --mixed : défaire le commit ET le staging (défaut)
git reset HEAD~1
# → Les fichiers restent modifiés mais non stagés
# --hard : TOUT effacer, revenir exactement à HEAD~1
git reset --hard HEAD~1
# ⚠ Danger : les modifications non commitées sont PERDUES
Reset vers un commit précis
# Revenir à un commit spécifique
git reset --hard abc1234
# Défaire le staging d'un seul fichier
git reset HEAD fichier.txt
# équivalent moderne :
git restore --staged fichier.txt
--soft ou --mixed dans le doute.
5 · git reflog
git reflog est le filet de sécurité ultime de Git. Il enregistre tous les déplacements de HEAD,
même ceux qui "effacent" des commits. Un commit "perdu" peut être retrouvé via le reflog pendant ~90 jours.
Lire le reflog
git reflog
# Sortie typique :
a1b2c3d HEAD@{0}: reset: moving to HEAD~1
f4e5d6c HEAD@{1}: commit: feat: ajout page contact
b7c8d9e HEAD@{2}: commit: fix: correction bug #42
0a1b2c3 HEAD@{3}: checkout: moving from main to feature/contact
Récupérer des commits après un reset --hard
# Scénario : git reset --hard HEAD~3 effectué par erreur
git reflog
# → f4e5d6c HEAD@{1}: commit: feat: fonctionnalité importante
# Méthode 1 : revenir directement via le reflog
git reset --hard HEAD@{1}
# Méthode 2 : créer une nouvelle branche depuis l'état récupéré
git checkout -b recuperation HEAD@{1}
# Méthode 3 : via le hash direct
git checkout f4e5d6c
Reflog d'une branche spécifique
# Voir l'historique complet d'une branche
git reflog refs/heads/main
git reflog origin/main
# Afficher avec dates
git reflog --date=iso
gc.reflogExpire). Passé ce délai, les commits orphelins sont nettoyés par git gc.
6 · Réécriture d'historique
Git offre plusieurs façons de réécrire l'historique. Ces opérations sont puissantes mais doivent être utilisées avec précaution, surtout sur des branches partagées.
git commit --amend
# Modifier le message du dernier commit
git commit --amend -m "feat: nouveau message corrigé"
# Ajouter des fichiers oubliés sans changer le message
git add fichier-oublié.js
git commit --amend --no-edit
# Modifier auteur
git commit --amend --author="Alaa EL HUSSEIN <alaa@example.com>"
Force-push après réécriture
# ⚠ Danger : écrase l'historique distant
git push --force origin feature/login
# ✅ Mieux : --force-with-lease vérifie qu'on n'écrase pas le travail d'un autre
git push --force-with-lease origin feature/login
La Règle d'Or de Git
Ne jamais réécrire l'historique de commits déjà poussés et partagés avec d'autres. Un rebase, amend ou reset sur des commits publics crée des divergences pour tous les collaborateurs qui ont basé leur travail dessus. Réservez ces opérations aux branches locales ou aux branches de feature personnelles pas encore mergées.
Tableau récapitulatif : quel outil utiliser ?
| Besoin | Outil recommandé | Risque |
|---|---|---|
| Corriger le dernier message | git commit --amend | Faible (si pas encore pushé) |
| Fusionner plusieurs commits | git rebase -i squash | Moyen |
| Linéariser l'historique | git rebase main | Moyen |
| Défaire un commit (garder code) | git reset --soft | Faible |
| Tout effacer | git reset --hard | Élevé ⚠ |
| Récupérer après erreur | git reflog | Nul (lecture seule) |