(Traduction du texte original en anglais : Merge)
Merge
hg merge
Un merge (fusion) combine deux changesets séparés d'un dépôt en un changeset fusionné qui décrit comment ils se combinent. Fusionner est le processus joignant les points de deux branches en une seule, le plus souvent depuis le head courant.
Le processus de fusion est simple. Habituellement, vous voudrez fusionner le tip dans votre dossier de travai.
Ainsi vous lancer hg merge et Mercurial incorporera les changements depuis le tip vers vos modifications locales ; le Tip deviendra alors la seconde révision mère de votre dossier de travail.
La première étape de ce processus est de parcourrir l'historique des changesets et de trouver "l'ancêtre commun" des deux versions qui vont être fusionnées (rev 1). Ceci est fait sur un dépôt, fichier par fichier.
Pour les fichiers qui ont changés dans plusieurs changesets, un arbre de fusion à trois branches est testé en utilisant un programme de fusion pour ajouter les changements distants aux changements locaux. S'il y a des conflicts entre ces changements, l'utilisateur est généralement invité à les résoudre de manière interactive.
Après avoir terminé la fusion et vous être assuré(e) d'avoir un résultat correct dans votre répertoire de travail, vous devez encore valider vos changements. Cela crée un nouveau changeset fusionné (rev 4 dans l'exemple), fixant le résultat de la fusion que vous aviez préparée dans le répertoire de travail.
Mercurial ne vous permettra pas d'effectuer une autre fusion tant que vous n'aurez pas validé car cela comprometterait une partie importante de l'historique nécessaire aux futures fusions.
Comme d'habitude, le nouveau changeset créé devient le nouveau parent du répertoire de travail, qui n'a toujours qu'un seul parent (parent 1).
Référence manuel : http://www.selenic.com/mercurial/hg.1.html#merge
Voir aussi : FrenchTutorialMerge, ResolveConflict, MergeMultipleHeads
Détails techniques
Branches et fusions
Chaque répertoire de travail est potentiellement une branche et chaque utilisateur travaille effectivement sur sa propre branche. Lorsque Mercurial met à jour une branche dans un répertoire de travail, il se souvient du changeset qui conduit directement à elle pour que les prochains changesets aient le bon parent.
Pour fusionner deux branches, vous rapatriez leur head dans le même dépôt, faîtes un update sur l'une et une fusion vers l'autre, puis validez le résultat une fois que vous êtes satisfait de la fusion. Le changeset résultant a deux parents.
Mercurial décide quand une fusion est nécessaire en déterminant d'abord si le répertoire de travail contient des modifications non validées. Cette détermination transforme effectivement le répertoire de travail en une branche de la version validée sur laquelle elle est fondée. Si le répertoire de travail est un ancêtre ou descendant direct de la deuxième version que vous tentez de mettre à jour, Mercurial remplacera la version du répertoire de travail avec la nouvelle. Sinon, il fusionne les deux versions.
Fusion d'arbre
Fusioner une paire de graphes orientés acycliques (DAG) - l'arbre généalogique de l'historique des fichiers - nécessite de déterminer si les nœuds dans les différents arbres correspondent. Comparer le contenu des nœuds (ou des hash des contenus) est une erreur parce que cela ne prend pas en compte l'historique.
Cependant, utiliser le nodeid permet d'éviter cette erreur, car le nodeid décrit le contenu du fichier et sa position par rapport à la racine de l'arbre. Une fusion vérifie simplement si chaque nodeid dans l'arbre A est dans l'arbre B et réciproquement (par exemple en utilisant une table de hachage), et Mercurial ajoute les nouveaux nœuds au revlog en mode "ajout-seul" (append-only).
Fusion de manifestes
Pour fusionner des manifestes, d'abord les comparer et décider quels fichiers doivent être ajoutés, supprimés et fusionnés.
Pour chaque fichier à fusionner, effectuer un diagramme de fusion et résoudre les conflits comme préciser précédemment. Il est important de fusionner les fichiers en utilisant un DAG par fichier plutôt que juste un DAG par changeset comme l'illustre le diagramme suivant :
P P1 P2 AB |`-------v P2 clone P (ligne principale) aB AB fichier A est une modification de la ligne principale |`---v AB' fichier B est une modification de P2 | aB / | P1 clone P | ab/ | P1 modifie B | ab' | P1 fusionne depuis P2, les modifications de B génère un conflit | | A'B' P2 modifie A `---+--.| | a'B' P2 fusionne depuis la ligne principale, les modifications de A génèrent un conflit `--.| ??? selon l'ancêtre que nous choisissons, nous aurons à refaire manuellement la fusion de A, de B ou des deux mais si nous regardons les fichiers indépendemment, la fusion est facile
Le résultat est une version fusionnée dans le dossier de travail, attendant d'être validée.
Fusion entre dépôts
Une fonctionnalité clef de Mercurial est son aptitude à fusionner de manière décentralisée entre des dépôts indépendants. Chaque dépôt peut agir comme un serveur en lecture seule ou en tant que client. Un client tire (pull) à partir du serveur toutes les branches qu'il n'a pas vu et les ajoute à son arbre. Ce pull se fait en deux étapes:
- La recherche de nouvelles racines.
Cette partie commence par trouver tous les nouveaux heads et remonte depuis ceux-ci vers les premiers nœuds inconnus dans leurs branches respectives. Ces noeuds sont les racines utilisées pour calculer le changegroup : l'ensemble de tous les changesets partant de ces racines. Mercurial prend la peine de faire cette recherche en optimisant aussi bien la bande passante que les allers-retours.
- Pull d'un changegroup.
- Une fois les racines trouvées, le changegroup peut être transféré en un seul transfert de flux. Ce transfert est organisé comme un ensemble ordonné de deltas des changesets, des manifestes et des fichiers. De gros morceaux de deltas peuvent être ajouté directement au dépôt sans avoir à être "déballés", ainsi la transaction reste rapide.
(Voir WireProtocol pour plus de détails.)
Une fois que les modifications distantes ont été tirées dans le dépôt actuel, la fusion se produit comme expliqué ci-dessus.
Notes
La fusion avec ancêtre n'est pas permise, tant que le descendant fusionné est une branche nommée. Quelqu'un sait-il pourquoi ?