Rebaser Git
La page de manuel officielle de Git sur man7.org définit la fonction principale comme suit : « Reapply commits on top of another base tip ». Git prend les commits d’une branche et les réexécute, mais cette fois au-dessus d’un autre commit — généralement le HEAD actuel de la branche principale. Le résultat est que les commits de la branche de fonctionnalité semblent avoir été créés seulement après que les dernières modifications de la branche principale aient été ajoutées. Le code final est identique à une fusion, mais l’historique semble différent : linéaire au lieu de ramifié.
Étapes
1. Récupérez les dernières modifications
Avant de rebaser, vous devez récupérer les dernières modifications distantes. Utilisez `git fetch` pour mettre à jour les branches de suivi distant sans affecter votre travail local.git fetch origin
Cela récupère tous les nouveaux commits du dépôt distant, mais ne change rien à vos branches locales. Vous pouvez maintenant voir où se trouve `origin/main` par rapport à votre branche locale.
2. Passez à votre branche de fonctionnalité
Assurez-vous d’être sur la branche que vous voulez rebaser. Si vous êtes encore sur une autre branche, changez d’abord.git checkout feature-branch
Remplacez `feature-branch` par le nom de votre branche. Vérifiez avec `git branch` que vous êtes sur la bonne branche avant de continuer.
3. Rebasez sur la branche principale
Effectuez le rebase avec `origin/main` comme nouvelle base. Cela réapplique tous vos commits locaux au-dessus des derniers commits de la branche principale.git rebase origin/main
Git prend maintenant chaque commit de votre branche de fonctionnalité et le réapplique, un par un, au-dessus d’`origin/main`. Si des conflits surviennent, Git s’arrête et vous laisse les résoudre.
4. Résolvez les conflits
Si Git signale des conflits, ouvrez les fichiers en conflit. Git marque les conflits avec `<<<<<<<`, `=======` et `>>>>>>>`. Résolvez chaque conflit manuellement et enregistrez le fichier.git add fichier-en-conflit.txt
git rebase --continueGit continue avec le commit suivant. Répétez jusqu’à ce que tous les commits soient appliqués. Si vous voulez arrêter, utilisez `git rebase --abort` pour revenir à la situation d’avant le rebase.
5. Rebase interactif pour modifier l’historique
Utilisez `git rebase -i` pour modifier activement l’historique. Cela ouvre un éditeur avec une liste de commits. La commande `git rebase -i HEAD~3` affiche les trois derniers commits.git rebase -i HEAD~3
Dans l’éditeur, vous voyez des lignes comme `pick a1b2c3d Message-du-commit`. Vous pouvez remplacer `pick` par l’une de ces options :
- `reword` — modifie uniquement le message du commit
- `edit` — modifie le contenu du commit
- `squash` — fusionne le commit avec le précédent
- `fixup` — fusionne sans conserver le message
- `drop` — supprime le commit
6. Push après un rebase
Si la branche avait déjà été poussée auparavant, vous devez effectuer un force push. Cela est nécessaire car les identifiants des commits ont changé à cause du rebase.git push --force-with-lease origin feature-branch
`--force-with-lease` est plus sûr que `--force` : il refuse le push si quelqu’un d’autre a poussé de nouveaux commits vers la branche entre-temps.
7. Rebase avec git-rerere
Pour les flux de travail avec des rebases fréquents, vous pouvez activer `git-rerere`. Cet outil réutilise automatiquement les conflits de fusion résolus.git config --global rerere.enabled true
Lorsque vous résolvez un conflit, Git enregistre la solution. Au prochain conflit similaire, Git applique automatiquement la solution enregistrée.
8. Vérifiez le résultat avec git-range-diff
`git-range-diff` compare deux plages de commits — par exemple avant et après un rebase. Cela montre ce qui a exactement changé dans l’historique.git range-diff origin/main...main feature-branch...feature-branch
Cette commande compare les plages de commits et affiche pour chaque commit les modifications effectuées. C’est utile lorsque plusieurs commits ont été réécrits ou fusionnés.
Vérification
Vérifiez si le rebase a réussi avec :git log --oneline --graph --decorate
Cela affiche l’historique des commits. Vous verrez une ligne linéaire sans embranchements. Les commits de votre branche de fonctionnalité se trouvent au-dessus des derniers commits d’`origin/main`. Aucun commit de fusion n’est visible.
Vérifiez aussi que le code fonctionne correctement :
git status
Cela doit afficher « nothing to commit, working tree clean » si tous les conflits ont été résolus et que le rebase est terminé.
Problèmes fréquents
1. «Cannot rebase: You have unstaged changes»
Git refuse de rebaser avec des modifications non validées. Résolvez ceci en mettant vos modifications de côté avec stash :git stash
git rebase origin/main
git stash popLe stash est réappliqué après le rebase.
2. Le conflit revient à chaque commit
Lorsque le même conflit se produit à chaque commit, utilisez `git-rerere`. Activez-le avant de démarrer le rebase :git config --global rerere.enabled true
Git enregistre votre solution la première fois et l’applique ensuite automatiquement.
3. «Updates were rejected» lors du push
Cela signifie que la branche distante diffère de votre branche locale après le rebase. Utilisez `--force-with-lease` :git push --force-with-lease origin feature-branch
Cela écrase la branche distante, mais refuse si d’autres ont poussé de nouveaux commits.
Pourquoi rebaser est dangereux
`git rebase` réécrit l’historique et modifie ainsi les identifiants de commit. Si une branche a déjà été partagée avec d’autres, ils verront une divergence entre leur historique local et la version partagée. La règle est donc : rebaser sur des commits qui n’ont pas encore été poussés ou partagés est sûr ; rebaser sur un historique partagé est déconseillé. `git reset` et `git restore` jouent aussi un rôle dans la gestion de l’historique, mais ne remplacent pas `rebase`. `git reset` replace HEAD sur un commit antérieur — destructif. `git restore` restaure des fichiers dans le répertoire de travail ou l’index, utile après une erreur dans un rebase interactif.Le terme « rebase » est utilisé depuis les débuts de Git. Un document howto sur kernel.org, daté du 14 août 2005, décrit le concept de « forward port these changes » — le transfert de modifications depuis un point de divergence vers la branche principale. C’était alors une procédure manuelle ; elle a rapidement été automatisée dans la commande `git rebase`. La spécification technique se trouve dans la page de manuel `git-rebase(1)`, maintenue par Junio C. Hamano et Johannes E. Schindelin, dont les noms et adresses e-mail figurent sur la page telle que publiée sur Linux die.net. La page de manuel actuelle sur man7.org confirme la même définition de base : « Reapply commits on top of another base tip ».
Outre le noyau Git, il existe des outils qui prennent en charge les flux de travail avec rebase. Gitpulsar, un client Git natif pour GNOME écrit en Rust, offre une interface rapide et fonctionnant hors ligne, sans télémétrie. Commit est un éditeur qui aide à rédiger de meilleurs messages de commit. Ces outils ne remplacent pas `git rebase`, mais soutiennent des flux de travail où la commande est régulièrement utilisée.
La question essentielle reste : voulez-vous un historique qui reflète précisément ce qui s’est passé, ou un historique qui reflète ce qui aurait dû se passer ?