Introduction
La base de merge de deux commits est leur meilleur ancêtre commun : la fondation que Git utilise pour les merges trois-voies. Choisir la bonne base est ce qui fait que les merges « automatiques » fonctionnent réellement.
La trouver
git merge-base A B
git merge-base --all A B # tous les meilleurs ancêtres communs
git merge-base --octopus A B C
git merge-base --is-ancestor X Y # exit 0 si X est ancêtre de Y
git merge-base --fork-point main feature
Définition
Un ancêtre commun C de A et B est un « meilleur » ancêtre commun si aucun autre ancêtre commun de A et B n'est descendant de C. La plupart des paires ont un seul meilleur ancêtre commun. Quand le graphe contient des merges croisés, plusieurs peuvent exister ; c'est ce que --all rapporte.
Comment le merge trois-voies l'utilise
Étant donné les commits A et B avec base de merge M, Git pour chaque fichier :
- Lit le fichier à M, A et B.
- Si seul un côté a changé, prend ce côté.
- Si les deux côtés ont changé identiquement, prend l'un ou l'autre.
- Si les deux côtés ont changé différemment, exécute un merge texte trois-voies ou émet des marqueurs de conflit.
Stratégies recursive et ort
Quand plusieurs bases de merge existent, la stratégie recursive les merge d'abord, produisant une base virtuelle, et l'utilise pour le merge trois-voies final. La stratégie ort (par défaut depuis 2.33) fait la même chose avec une implémentation plus rapide et plus efficace en mémoire.
git merge -s ort feature
git merge -s recursive feature
git merge -s resolve feature # une seule base de merge, pas de récursion
Fork point
Pour rebase, Git a souvent besoin de savoir où une branche thématique a quitté une branche de base. --fork-point consulte le reflog de la base pour trouver le point le plus récent où la thématique et la base partageaient l'historique :
git rebase --fork-point main feature
git merge-base --fork-point main feature
Exemple résolu
A---B---C main
\
D---E feature
git merge-base main feature # B
Un merge de main dans feature fait un merge trois-voies en utilisant B comme base.
Inspecter pourquoi un merge entre en conflit
git merge-base HEAD feature
git diff <base> HEAD -- file
git diff <base> feature -- file
Cette paire de diffs est exactement ce que le merge de Git voit.
Erreurs fréquentes
Supposer qu'il y a toujours exactement une base de merge ; les historiques croisés en produisent plusieurs. Traiter --fork-point comme un substitut à --onto ; ils résolvent des problèmes différents. Choisir --strategy=ours alors que vous vouliez --strategy-option=ours ; le premier abandonne entièrement leurs changements. Enfin, recalculer la base de merge à la main à partir de la sortie de git log et se tromper ; utilisez git merge-base plutôt que d'estimer à l'œil.