Cette page est une traduction de l'original en anglais TutorialMerge.
Tutorial - Fusionner les changements
(Cette page est la partie 7 sur 9 de la série FrenchTutorial. La partie précédente est FrenchTutorialExport, la suivante FrenchTutorialConflict)
Dans FrenchTutorialExport, nous avons appris comment partager les changements avec d'autres personnes. Ici, nous allons montrer la fusion (merge) en récupérant (pull) à partir d'un autre dépôt qui contient des changements divergents.
Tout d'abord, nous devons créer quelque chose à fusionner. Clonons le dépôt mon-hello de nouveau.
$ cd .. $ hg clone mon-hello my-hello-desc updating working directory 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
Nous allons donner à hello.c une description dans sa section commentaire.
$ cd my-hello-desc $ vi hello.c
Modifions la seconde ligne à partir de ceci :
* hello.c
Vers ceci :
* hello.c - hello, world
Sauvons et quittons l'éditeur, et soumettons (commit) nos changements. Cette fois-ci, nous gagnons un peu de temps en utilisant l'option -m de la commande commit qui permet de ne pas être renvoyé vers un éditeur :
$ hg commit -m "Add description of hello.c"
A ce point, nous avons fait un changement dans hello.c dans le dépôt my-hello-new-output, et un autre changement à hello.c dans le dépôt my-hello-desc. Comment va-t-on "fusionner" ces deux lignes divergentes de développement ? Va-t-il y avoir un problème lorsque nous ferons un pull de l'un à l'autre ?
Ça marche simplement parfaitement. Pendant que nous sommes encore dans my-hello-desc, faisons un pull des changements de my-hello-new-output et regardons ce qui se passe :
$ hg pull ../my-hello-new-output pulling from ../my-hello-new-output searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge)
Mercurial nous dit qu'il a ajouté un head additionnel à notre dépôt. Pour voir les heads, nous pouvons utiliser la commande heads :
$ hg heads changeset: 3:86794f718fb1 tag: tip parent: 1:82e55d328c8c user: mpm@selenic.com date: Mon May 05 01:20:46 2008 +0200 summary: Express great joy at existence of Mercurial changeset: 2:c3844fde99f0 user: mpm@selenic.com date: Tue May 06 20:10:35 2008 +0200 summary: Add description of hello.c
Mercurial arrive avec une jolie extension qui peut montrer dans un graphe ASCII l'historique d'un dépôt : l'extension GraphlogExtension. Tout ce que vous avez besoin de faire pour pour faire fonctionner cette extension est de l'activer dans votre fichier ~/.hgrc (ou Mercurial.ini sous Windows) en ajoutant la ligne hgext.graphlog = à la section [Extension] ainsi :
[extensions] hgext.graphlog =
Si vous avez fait cela, une commande additionnelle glog devient maintenant disponible (cf. aussi hg help glog) :
$ hg glog o changeset: 3:86794f718fb1 | tag: tip | parent: 1:82e55d328c8c | user: mpm@selenic.com | date: Mon May 05 01:20:46 2008 +0200 | summary: Express great joy at existence of Mercurial | | @ changeset: 2:c3844fde99f0 |/ user: mpm@selenic.com | date: Tue May 06 20:10:35 2008 +0200 | summary: Add description of hello.c | o changeset: 1:82e55d328c8c | user: mpm@selenic.com | date: Fri Aug 26 01:21:28 2005 -0700 | summary: Create a makefile | o changeset: 0:0a04b987be5a user: mpm@selenic.com date: Fri Aug 26 01:20:50 2005 -0700 summary: Create a standard "hello, world" program
Dans ce graphe, vous pouvez voir que nous venons de rapatrier le ChangeSet 86794f718fb1 dans notre dépôt (qui correspond à celui avec le tip). Tant que les deux ne sont pas rapatriés dans le 86794f718fb1 et que notre propre c3844fde99f0 a été commité vers la même base 82e55d328c8c (le parent), une ligne de développement divergente – appelée une branche – a été créée. Notez que dans ce cas, cette branche a eu une durée de vie assez courte et traiter cet écart est simple à résoudre avec Mercurial.
En regardant la sortie de pull, vous devriez penser que ça ressemble beaucoup à ce que l'on a vu dans FrenchTutorialShareChange. Donc vous pourriez demander : pourquoi ne pas simplement faire un simple update maintenant comme nous l'avions fait dans FrenchTutorialShareChange ? Essayons pour voir ce qu'il se passe :
$ hg update abort: crosses branches (use 'hg merge' or 'hg update -C')
Quelque chose est clairement différent ici. Mais comme vous pouvez le voir, Mercurial fait attention à ne pas faire quelque chose de stupide, donc, si nous voyons quand même quelque chose comme une notice "(+1 heads)" après un pull, nous pouvons être sûr que Mercurial va nous rappeler que nous devrions probablement faire quelque chose ici : nous devrions fusionner (merge).
Mais avant de faire notre première fusion, regardons à quel ChangeSet nous sommes synchronisés. Nous pouvons utiliser la commande parents pour le faire (cf. parent) :
$ hg parents changeset: 2:c3844fde99f0 user: mpm@selenic.com date: Tue May 06 20:10:35 2008 +0200 summary: Add description of hello.c
Ceci nous montre que le contenu de notre répertoire de travail est toujours synchronisé avec le ChangeSet c3844fde99f0 – après tout, il s'agit de ce que nous venons de committer. Ce qui est important de comprendre ici, c'est que le pull que nous venons de faire n'a apporté les changements qu'à l'entrepôt de notre dépôt. Le pull n'a rien changé dans notre répertoire de travail. Et avec un second regard à la sortie de glog : un ChangeSet est marqué avec un @. C'est le parent de notre répertoire de travail : nous sommes au ChangeSet c3844fde99f0.
Donc, allons finalement fusionner maintenant. Fusionner a l'air difficile, non ? C'est en fait très simple. Suivons les instructions de la dernière ligne de notre pull un peu plus tôt :
$ hg merge merging hello.c 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit)
C'est tout ce qu'il y a ici ! Mercurial était capable de traiter la fusion automatiquement pour vous puisque les changements n'étaient pas en conflits (les fusions avec conflits seront traitées dans FrenchTutorialConflict). Si nous regardons maintenant à hello.c dans le répertoire de travail, nous remarquons qu'il contient les changements de my-hello-new-output et de my-hello-desc.
Lorsque l'on travaille avec les changements effectués par d'autres personnes, c'est le type de fusion que vous allez devoir traiter la plupart du temps. Le plus souvent, c'est même plus simple que ça et les fichiers qui sont changés dans les lignes de développement sont distincts. Donc, dans la plupart des fusions, il n'y aura aucun fichier à fusionner.
Nous n'avons pas encore commité cette fusion. Avant de le faire, regardons ce que la commande parents nous renvoie maintenant (nous utilisons l'abréviation par) :
$ hg par changeset: 2:c3844fde99f0 user: mpm@selenic.com date: Tue May 06 20:10:35 2008 +0200 summary: Add description of hello.c changeset: 3:86794f718fb1 tag: tip parent: 1:82e55d328c8c user: mpm@selenic.com date: Mon May 05 01:20:46 2008 +0200 summary: Express great joy at existence of Mercurial
Ceci nous informe maintenant que le répertoire de travail est basé sur deux ChangeSets : il possède deux parents. Notez que ces deux parents sont ordonnés : le premier parent (parent 1) est notre !Changeset le plus ancien c3844fde99f0 dans lequel nous avons ajouté une description à hello.c. Celui ci était le parent actuel lorsque nous avons utilisé la commande merge. Le second parent (parent 2) est le ChangeSet 86794f718fb1 que nous avons récupéré depuis l'autre dépôt et que nous venons juste de fusionner.
Un autre glob nous montre maintenant le signe @ devant les deux parents :
$ hg glog @ changeset: 3:86794f718fb1 | tag: tip | parent: 1:82e55d328c8c | user: mpm@selenic.com | date: Mon May 05 01:20:46 2008 +0200 | summary: Express great joy at existence of Mercurial | | @ changeset: 2:c3844fde99f0 |/ user: mpm@selenic.com | date: Tue May 06 20:10:35 2008 +0200 | summary: Add description of hello.c | o changeset: 1:82e55d328c8c | user: mpm@selenic.com | date: Fri Aug 26 01:21:28 2005 -0700 | summary: Create a makefile | o changeset: 0:0a04b987be5a user: mpm@selenic.com date: Fri Aug 26 01:20:50 2005 -0700 summary: Create a standard "hello, world" program
Notez que si vous changez d'avis et voulez annuler la fusion avant de committer quoi que ce soit, le simple fait de faire un hg revert -r2 --all va seulement revenir à l'état de la révision 2 des fichiers dans le répertoire de travail mais ne pas changer les parents du répertoire de travail à un seul parent (cf. revert). Vous devriez plutôt faire un "hg update -C -r." dans ce cas.
Pour compléter l'ensemble de la procédure de fusion, nous ne devons pas oublier de commiter les modifications locales, comme suggéré à la dernière ligne de notre commande merge :
$ hg commit -m "Merged changes from my-hello-new-output"
Il ne devrait pas y avoir de sortie pour cette commande. Maintenant, la fusion est enregistrée dans l'entrepôt de notre dépôt comme un nouveau ChangeSet de fusion que nous pouvons explorer avec un glog :
$ hg glog @ changeset: 4:d2ecac0134d8 |\ tag: tip | | parent: 2:c3844fde99f0 | | parent: 3:86794f718fb1 | | user: mpm@selenic.com | | date: Tue May 06 23:44:19 2008 +0200 | | summary: Merged changes from my-hello-new-output | | | o changeset: 3:86794f718fb1 | | parent: 1:82e55d328c8c | | user: mpm@selenic.com | | date: Mon May 05 01:20:46 2008 +0200 | | summary: Express great joy at existence of Mercurial | | o | changeset: 2:c3844fde99f0 |/ user: mpm@selenic.com | date: Tue May 06 20:10:35 2008 +0200 | summary: Add description of hello.c | o changeset: 1:82e55d328c8c | user: mpm@selenic.com | date: Fri Aug 26 01:21:28 2005 -0700 | summary: Create a makefile | o changeset: 0:0a04b987be5a user: mpm@selenic.com date: Fri Aug 26 01:20:50 2005 -0700 summary: Create a standard "hello, world" program
Pour montrer les changements de notre fusion, nous pouvons utiliser en plus la commande annotate pour montrer les informations du ChangeSet pour chaque ligne des fichiers. Notez que la révision 2 est notre modification au dépôt my-hello-desc et la révision 3 contient les changements récupérés du dépôt my-hello-new-output et fusionnés au dépôt my-hello-desc.
$ hg annotate hello.c 0: /* 2: * hello.c - hello, world 0: * 0: * Placed in the public domain by Bryan O'Sullivan 0: * 0: * This program is not covered by patents in the United States or other 0: * countries. 0: */ 0: 0: #include <stdio.h> 0: 0: int main(int argc, char **argv) 0: { 0: printf("hello, world!\n"); 3: printf("sure am glad I'm using Mercurial!\n"); 0: return 0; 0: }
Continuons maintenant avec l'apprentissage de comment résoudre les situations conflictuelles dûs aux changements faits dans FrenchTutorialConflict.