Introduction
Un merge combine deux lignes de développement. Le cas le plus courant est de ramener une branche de feature dans main. Cette page parcourt un merge propre, un fast-forward et un merge avec conflits.
Mise en place
git switch -c feature/greeting
echo "hello world" > greeting.txt
git add greeting.txt
git commit -m "Add greeting"
git switch main
git merge feature/greeting
Si main n'a pas bougé depuis la création de la branche, Git fait un fast-forward : il déplace simplement le pointeur de main vers la pointe de feature/greeting. Aucun merge commit n'est créé.
Vrais merges trois-voies
Si les deux branches ont de nouveaux commits, Git crée un merge commit avec deux parents :
git switch main
echo "main change" >> notes.txt
git commit -am "Update notes on main"
git merge feature/greeting
# Merge made by the 'ort' strategy.
Le premier parent du merge commit est le précédent HEAD de main ; son second parent est la pointe de la branche mergée.
Forcer un merge commit
Pour préserver l'historique visiblement même quand un fast-forward est possible :
git merge --no-ff feature/greeting -m "Merge feature/greeting"
Conflits
Si les deux côtés ont édité les mêmes lignes, Git s'arrête et écrit des marqueurs de conflit :
<<<<<<< HEAD
line from main
=======
line from feature
>>>>>>> feature/greeting
Résolvez en éditant le fichier, puis :
git add notes.txt
git status
git commit # utilise le message de merge préparé
Annuler
Si vous changez d'avis en cours de merge :
git merge --abort
Cela restaure l'arborescence de travail à l'état pré-merge.
Inspecter le résultat
git log --oneline --graph --decorate -n 10
Le graphe montre la forme en losange créée par le merge.
Inspecter un merge
Les merge commits ont deux parents, donc les diffs nécessitent une gestion explicite. git show sur un merge utilise par défaut un « combined diff » qui ne met en évidence que les changements en conflit avec les deux parents :
git show HEAD # combined diff
git show -m HEAD # diff contre chaque parent séparément
git show --first-parent HEAD # contre le premier parent seulement
git log --merges --oneline # uniquement merge commits
git log --no-merges --oneline # excluant merge commits
Pour l'archéologie de code, --first-parent sur une branche de longue durée révèle l'histoire d'intégration : quand chaque feature a atterri, dans l'ordre chronologique du tronc.
Erreurs fréquentes
Éditer des fichiers pendant un merge mais oublier de les git add, donc git commit se plaint encore des chemins non résolus. Exécutez toujours git status après avoir édité. Résoudre en supprimant les marqueurs de conflit mais en laissant du texte obsolète d'un côté ; faites un build et exécutez les tests avant de commiter le merge. Utiliser --no-ff sur chaque merge dans un dépôt à évolution rapide, polluant l'historique avec des merge commits vides. Enfin, paniquer à l'invite et exécuter git reset --hard en plein merge ; git merge --abort est plus sûr parce qu'il connaît ORIG_HEAD.