Merge vs Rebase
C'est l'une des décisions les plus importantes dans Git. Les deux servent à intégrer des changements d'une branche dans une autre, mais de manière différente.
Imaginez deux chemins qui se rejoignent.
- Merge : Les deux chemins fusionnent en un point de rencontre
- Rebase : Un chemin est déplacé pour partir du bout de l'autre
Le Merge : Fusionner avec historique
Le merge fusionne deux branches en créant un commit de merge qui a deux parents.
Situation initiale
main → A → B → C
↓
feature → D → E
Après git merge feature depuis main :
main → A → B → C ────→ F (merge commit)
↓ ↗
feature → D → E ───┘
Un nouveau commit F est créé, qui relie C (main) et E (feature).
Commandes
# 1. Se placer sur la branche de destination
git checkout main
# 2. Récupérer les derniers changements
git pull
# 3. Fusionner la branche feature
git merge feature
Résultat :
Merge made by the 'recursive' strategy.
src/feature.js | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
Avantages
- Préserve l'historique complet : On voit clairement quand et comment les branches ont été développées
- Sûr : N'altère jamais les commits existants
- Simple : Facile à comprendre pour les débutants
- Traçabilité : Les branches parallèles restent visibles dans l'historique
Inconvénients
- Historique chargé : Beaucoup de commits de merge si on merge souvent
- Graphe complexe : L'historique devient un labyrinthe avec beaucoup de branches
- "Bruit" visuel : Les commits de merge n'apportent pas de code, juste de la fusion
Le Rebase : Réécrire pour un historique linéaire
Le rebase réapplique vos commits un par un sur une autre branche, créant un historique linéaire.
Situation initiale :
main → A → B → C
↓
feature → D → E
Après git rebase main depuis feature :
main → A → B → C
↓
feature → D' → E'
Les commits D et E sont réécrits en D' et E' (nouveaux hash) et réappliqués après C.
Commandes
# 1. Se placer sur la branche à rebaser
git checkout feature
# 2. Rebaser sur main
git rebase main
Résultat :
Successfully rebased and updated refs/heads/feature.
Vos commits de
featuresont maintenant après le dernier commit demain.
Avantages
- Historique linéaire : Facile à lire, comme une ligne droite
- Pas de commits de merge : Historique propre et clair
- Facilite le debugging : Plus simple de trouver des
bugs avec
git bisect - Professionnel : Préféré par beaucoup d'équipes et projets open source
Inconvénients
- Réécrit l'historique : Change les hash des commits ( problématique si déjà partagés)
- Conflits multiples : Peut nécessiter de résoudre des conflits plusieurs fois
- Dangereux sur branches partagées : Peut créer des problèmes énormes pour l'équipe
- Courbe d'apprentissage : Plus complexe à comprendre au début
Précautions
NE JAMAIS REBASER DES COMMITS QUI ONT ÉTÉ PUSHÉS SUR UNE BRANCHE PARTAGÉE
Le rebase réécrit l'historique en créant de nouveaux commits avec de nouveaux hash. Si quelqu'un d'autre a basé son travail sur vos anciens commits, vous allez créer un chaos dans l'équipe.
Quand puis-je rebaser en toute sécurité ?
| Vous POUVEZ rebaser | Ne JAMAIS rebaser |
|---|---|
| Votre branche de feature personnelle (pas encore pushée) | La branche main ou master |
| Votre branche pushée où vous êtes le seul contributeur | La branche develop ou toute branche partagée |
| Votre branche locale pour la nettoyer avant une Pull Request | Toute branche sur laquelle plusieurs personnes travaillent |
| Vos commits locaux non partagés | Des commits déjà présents sur le serveur distant |
Lequel choisir ?
| Situation | Recommandation | Pourquoi |
|---|---|---|
Intégrer main dans votre feature | Rebase | Garde votre feature à jour avec un historique propre |
Merger votre feature dans main | Merge | Préserve l'historique et la traçabilité |
| Mettre à jour votre branche locale | Rebase | Évite les commits de merge inutiles |
| Branche partagée avec d'autres | Merge | Sûr, ne réécrit pas l'historique |
| Nettoyer l'historique avant PR | Rebase | Présente un historique propre aux reviewers |
Branches publiques (main, develop) | Merge | Ne jamais réécrire l'historique public |
Autres commandes utiles
Cherry-pick
git cherry-pick a1b2c3d
Applique le commit a1b2c3d sur votre branche actuelle.
Cas d'usage : Vous avez committé un bugfix sur la mauvaise branche.
Tags
# Créer un tag annoté (recommandé)
git tag -a v1.0.0 -m "Release version 1.0.0"
# Pousser un tag
git push origin v1.0.0
# Pousser tous les tags
git push --tags
Les tags sont utilisés pour marquer des releases importantes (v1.0.0, v2.0.0, etc.).
Tableau récapitulatif
| Commande | Description |
|---|---|
git merge branche | Fusionner une branche (crée un commit de merge) |
git rebase branche | Rebaser sur une branche (historique linéaire) |
git rebase -i HEAD~N | Rebase interactif (nettoyer l'historique) |
git merge --abort | Annuler un merge en cours |
git rebase --abort | Annuler un rebase en cours |
git rebase --continue | Continuer après résolution de conflit |
git cherry-pick commit | Appliquer un commit spécifique |
git tag -a v1.0.0 -m "msg" | Créer un tag annoté |