Il est maintenant généralement admis que l'algorithme de fusion à 3 voies (peut-être avec des améliorations telles que la détection des renommages et le traitement d'un historique plus compliqué), qui prend en compte la version de la branche actuelle ('la nôtre'), la version de la branche fusionnée ('la leur'), et la version de l'ancêtre commun des branches fusionnées ('l'ancêtre') est (d'un point de vue pratique) la meilleure façon de résoudre les fusions. Dans la plupart des cas, et pour la plupart des contenus, la fusion au niveau de l'arbre (quelle version du fichier prendre) est suffisante ; il est rarement nécessaire de traiter les conflits de contenu, et l'algorithme diff3 est alors suffisant.
Pour utiliser la fusion à trois, vous devez connaître l'ancêtre commun des branches fusionnées (appelé aussi base de fusion). Pour cela, vous devez connaître complet l'histoire entre ces branches. Ce qui manquait à Subversion avant la version (actuelle) 1.5 (sans outils tiers comme SVK ou svnmerge), c'était suivi des fusions c'est-à-dire qu'il faut se rappeler pour chaque commit de fusion quels parents (quels commits) ont été utilisés dans la fusion. Sans cette information, il n'est pas possible de calculer correctement l'ancêtre commun en présence de fusions répétées.
Prenez en compte le schéma suivant :
---.---a---.---b---d---.---1
\ /
\-.---c/------.---2
(qui sera probablement maltraité... ce serait bien d'avoir la possibilité de dessiner des diagrammes ASCII-art ici) .
Lorsque nous avons fusionné les commits 'b' et 'c' (créant le commit 'd'), l'ancêtre commun était le point de branchement, le commit 'a'. Mais lorsque nous voulons fusionner les commits '1' et '2', l'ancêtre commun est maintenant le commit 'c'. Sans le stockage des informations de fusion, nous devrions conclure à tort que c'est le commit 'a'.
Subversion (avant la version 1.5), et les versions antérieures de CVS, rendaient la fusion difficile parce que vous deviez calculer vous-même l'ancêtre commun, et donner des informations sur l'ancêtre manuellement lors d'une fusion.
Git stocke des informations sur tous les parents d'un commit (plus d'un parent dans le cas d'un commit de fusion) dans l'objet commit. De cette façon, on peut dire que Git stocke le DAG (direct acyclic graph) des révisions, en stockant et en se souvenant des relations entre les commits.
(Je ne suis pas sûr de la façon dont Subversion traite les problèmes mentionnés ci-dessous).
En outre, la fusion dans Git peut traiter deux problèmes de complication supplémentaires : renommage de fichiers (lorsqu'une partie a renommé un fichier, et que l'autre ne l'a pas fait ; nous voulons obtenir le renommage, et nous voulons que les changements soient appliqués au bon fichier) et fusions croisées (histoire plus compliquée, lorsqu'il y a plus d'un ancêtre commun).
-
Renommages de fichiers pendant la fusion sont gérés en utilisant un score de similarité heuristique (la similarité du contenu du fichier et celle du nom du chemin d'accès sont prises en compte). détection de renommage . Git détecte quels fichiers correspondent les uns aux autres dans les branches fusionnées (et les ancêtres). En pratique, cela fonctionne assez bien pour les cas réels.
-
Fusions croisées voir définition au wiki revctrl.org (et présence de bases de fusion multiples ) sont gérés en utilisant stratégie de fusion récursive ce qui génère un seul ancêtre commun virtuel.