hgbook

view fr/ch03-tour-merge.xml @ 1032:a55f319bcc67

Merge with Romain Pelisse
author Bryan O'Sullivan <bos@serpentine.com>
date Sat Jul 10 06:24:49 2010 +0100 (2010-07-10)
parents c859c8d32838
children
line source
1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
3 <chapter id="chap:tour-merge">
4 <?dbhtml filename="a-tour-of-mercurial-merging-work.html"?>
5 <title>Un tour rapide de Mercurial : fusionner les travaux</title>
7 <para id="x_338">Nous avons maintenant étudié comment cloner un dépôt, effectuer
8 des changements dedans, et récupérer ou transférer depuis un
9 autre dépôt. La prochaine étape est donc de <emphasis>fusionner</emphasis> les
10 modifications de différents dépôts.</para>
12 <sect1>
13 <title>Fusionner différents travaux</title>
14 <para id="x_339">La fusion est un aspect fondamental lorsqu'on
15 travaille avec un gestionnaire de révisions distribué.</para>
17 <itemizedlist>
18 <listitem>
19 <para id="x_33a">Alice et Bob ont chacun une copie personnelle du dépôt d'un
20 projet sur lequel ils collaborent. Alice corrige un bug
21 dans son dépôt, et Bob ajoute une nouvelle fonctionnalité dans le
22 sien. Ils veulent un dépôt partagé avec à la fois le correctif du
23 bug et la nouvelle fonctionnalité.</para>
24 </listitem>
25 <listitem>
26 <para id="x_33b">Je travaille régulièrement sur plusieurs tâches différentes sur
27 un seul projet en même temps, chacun isolé dans son propre dépôt.
28 Travailler ainsi signifie que je dois régulièrement fusionner une
29 partie de mon code avec celui des autres.</para>
30 </listitem>
31 </itemizedlist>
33 <para id="x_33c">Parce que nous devons fusionner souvent,
34 Mercurial rend cette opération facile. Étudions ensemble le déroulement des
35 opérations. Nous commencerons encore par faire un clone d'un autre
36 dépôt (vous voyez que l'on fait ça tout le temps ?) puis nous ferons
37 quelques modifications dessus.</para>
39 &interaction.tour.merge.clone;
41 <para id="x_33d">Nous devrions avoir maintenant deux copies de
42 <filename>hello.c</filename> avec des contenus différents. Les
43 historiques de ces deux dépôts ont aussi divergés, comme illustré dans
44 la figure <xref linkend="fig:tour-merge:sep-repos"/>.</para>
46 &interaction.tour.merge.cat1;
48 <para id="x_722">Et ici se trouve notre version légèrement différente du
49 dépôt.</para>
51 &interaction.tour.merge.cat2;
53 <figure id="fig:tour-merge:sep-repos">
54 <title>Historique divergeant des dépôts <filename
55 class="directory">my-hello</filename> et <filename
56 class="directory">my-new-hello</filename>.</title>
57 <mediaobject>
58 <imageobject><imagedata fileref="figs/tour-merge-sep-repos.png"/></imageobject>
59 <textobject><phrase>XXX ajoute un test</phrase></textobject>
60 </mediaobject>
61 </figure>
63 <para id="x_33f">Nous savons déjà que récupérer les modifications depuis
64 notre dépôt <filename class="directory">my-hello</filename> n'aura
65 aucun effet sur l'espace de travail.</para>
67 &interaction.tour.merge.pull;
69 <para id="x_340">Néanmoins, la commande <command role="hg-cmd">hg
70 pull</command> nous indique quelque chose au sujet des
71 <quote>heads</quote>.</para>
73 <sect2>
74 <title>Les révisions <quote>heads</quote></title>
76 <para id="x_341">Rappelez vous que Mercurial enregistre quelle révision
77 est le parent de chaque révision. Si une révision a un parent, nous
78 l'appelons un enfant <quote>child</quote> ou un descendant de ce parent. Une
79 <quote>head</quote> est une révision qui n'a donc pas d'enfant. La révision <quote>tip</quote>
80 est donc une <quote>head</quote>, car c'est la révision la plus récente du dépôt
81 qui n'a pas d'enfant. Il y a des moments où un dépôt peut contenir
82 plusieurs <quote>heads</quote>.</para>
84 <figure id="fig:tour-merge:pull">
85 <title>Contenu du dépôt après une récupération (pull) depuis le
86 dépôt <filename
87 class="directory">my-hello</filename> vers le dépôt <filename
88 class="directory">my-new-hello</filename></title>
89 <mediaobject>
90 <imageobject>
91 <imagedata fileref="tour-merge-pull"/>
92 </imageobject>
93 <textobject><phrase>XXX ajoute un texte</phrase></textobject>
94 </mediaobject>
95 </figure>
97 <para id="x_343">Dans la figure <xref linkend="fig:tour-merge:pull"/>,
98 vous pouvez constater l'effet d'un <quote>pull</quote> depuis le dépôt
99 <filename class="directory">my-hello</filename> dans le dépôt
100 <filename class="directory">my-new-hello</filename>. L'historique qui
101 était déjà présent dans le dépôt <filename
102 class="directory">my-new-hello</filename> reste intact, mais une
103 nouvelle révision a été ajoutée. En vous reportant à la figure <xref
104 linkend="fig:tour-merge:sep-repos"/>, vous pouvez voir que l'
105 <emphasis>ID de révision <quote>changeset ID</quote></emphasis> reste le même dans
106 le nouveau dépôt, mais que le <emphasis>numéro de
107 révision</emphasis> reste le même. (Ceci est un parfait exemple de
108 pourquoi il n'est fiable d'utiliser les numéros de révision lorsque
109 l'on discute d'un <quote>changeset</quote>.) Vous pouvez voir les <quote>heads</quote>
110 présentes dans le dépôt en utilisant la commande <command
111 role="hg-cmd">hg heads</command>.</para>
113 &interaction.tour.merge.heads;
114 </sect2>
116 <sect2>
117 <title>Effectuer la fusion</title>
119 <para id="x_344">Que se passe-t-il quand vous essayez d'utiliser la
120 commande <command role="hg-cmd">hg update</command> pour mettre à
121 jour votre espace de travail au nouveau <quote>tip</quote> ?</para>
123 &interaction.tour.merge.update;
126 <para id="x_345">Mercurial nous prévient que la commande <command
127 role="hg-cmd">hg update</command> n'effectuera pas
128 la fusion, il ne veut pas mettre à jour l'espace de travail quand il
129 estime que nous pourrions avoir besoin d'une fusion, à moins de lui
130 forcer la main. À la place, il faut utiliser la commande <command
131 role="hg-cmd">hg merge</command> pour fusionner les deux
132 <quote>heads</quote>.
133 <!--où se trouve la traduction de
134 (Incidentally, forcing the update with <command>hg update
135 -C</command> would revert any uncommitted changes in the
136 working directory.)-->
137 </para>
139 <para id="x_723">Pour commencer une fusion (merge) entre deux <quote>heads</quote>,
140 nous utilisons la commande <command role="hg-cmd">hg merge</command>.</para>
142 &interaction.tour.merge.merge;
144 <para id="x_347">Nous résolvons les conflits dans le fichier
145 <filename>hello.c</filename>. Ceci met à jour le répertoire de travail
146 de sorte qu'il ne contienne les modifications en provenance des
147 <emphasis>deux</emphasis> <quote>heads</quote>, ce qui est indiqué par la
148 la sortie de la commande <command role="hg-cmd">hg
149 parents</command> et le contenu du fichier
150 <filename>hello.c</filename>.</para>
152 &interaction.tour.merge.parents;
153 </sect2>
155 <sect2>
156 <title>Effectuer l'ajout (commit) du résultat de la fusion</title>
158 <para id="x_348">Dès l'instant où vous avez effectué une fusion
159 (merge), <command role="hg-cmd">hg parents</command> vous
160 affichera deux parents, avant que vous n'exécutiez la commande
161 <command role="hg-cmd">hg commit</command> sur le résultat de la
162 fusion.</para>
164 &interaction.tour.merge.commit;
166 <para id="x_349">Nous avons maintenant un nouveau tip, remarquez qu'il
167 contient <emphasis>à la fois</emphasis> nos anciennes <quote>heads</quote> et leurs
168 parents. Ce sont les mêmes révisions que nous avions affichées avec
169 la commande <command role="hg-cmd">hg parents</command>.</para>
171 &interaction.tour.merge.tip;
173 <para id="x_34a">Dans la figure <xref linkend="fig:tour-merge:merge"/>,
174 vous pouvez voir une représentation de ce qui se passe dans l'espace
175 de travail pendant la fusion, et comment ceci affecte le dépôt lors
176 du <quote>commit</quote>. Pendant la fusion, l'espace de travail, qui a deux
177 révisions (changesets) comme parents, voit ces derniers devenir le parent
178 d'une nouvelle révision (changeset).</para>
180 <figure id="fig:tour-merge:merge">
181 <title>Répertoire de travail et dépôt pendant une fusion,
182 et le <quote>commit</quote> qui suit</title>
183 <mediaobject>
184 <imageobject>
185 <imagedata fileref="figs/tour-merge-merge.png"/>
186 </imageobject>
187 <textobject><phrase>XXX ajoute texte</phrase></textobject>
188 </mediaobject>
189 </figure>
191 </sect2>
192 </sect1>
194 <sect1>
195 <title>Fusionner les modifications en conflit</title>
197 <para id="x_34b">La plupart des fusions sont assez simples à réaliser, mais
198 parfois vous vous retrouverez à fusionner des fichiers où la modification
199 touche la même portion de code, au sein d'un même fichier. À moins
200 que ces modification ne soient identiques, ceci aboutira à un
201 <emphasis>conflit</emphasis>, et vous devrez décider comment réconcilier
202 les différentes modifications dans un ensemble cohérent.</para>
204 <figure id="fig:tour-merge:conflict">
205 <title>Modifications en conflit dans un document</title>
206 <mediaobject>
207 <imageobject><imagedata fileref="tour-merge-conflict"/></imageobject>
208 <textobject><phrase>XXX ajoute texte</phrase></textobject>
209 </mediaobject>
210 </figure>
212 <para id="x_34d">La figure <xref linkend="fig:tour-merge:conflict"/>
213 illustre un cas de modifications conflictuelles dans un document. Nous
214 avons commencé avec une version simple de ce fichier, puis nous avons
215 ajouté des modifications, pendant que quelqu'un d'autre modifiait le même
216 texte. Notre tâche dans la résolution du conflit est de décider à quoi le
217 fichier devrait ressembler.</para>
219 <para id="x_34e">Mercurial n'a pas de mécanisme interne pour gérer
220 les conflits. À la place, il exécute un programme externe appelé
221 <command>hgmerge</command>. Il s'agit d'un script shell qui est
222 compris avec Mercurial, vous pouvez le modifier si vous voulez.
223 Ce qu'il fait par défaut est d'essayer de trouver un des différents
224 outils de fusion qui seront probablement installés sur le système.
225 Il commence par les outils totalement automatiques, et s'ils
226 échouent (parce que la résolution du conflit nécessite une
227 intervention humaine) ou s'ils sont absents, le script tente
228 d'exécuter certains outils graphiques de fusion.</para>
230 <para id="x_34f">Il est aussi possible de demander à Mercurial d'exécuter
231 un autre programme ou un autre script en définissant la variable
232 d'environnement <envar>HGMERGE</envar> avec le nom
233 du programme de votre choix.</para>
235 <sect2>
236 <title>Utiliser un outil graphique de fusion</title>
238 <para id="x_350">Mon outil de fusion préféré est
239 <command>kdiff3</command>, que j'utilise ici pour illustrer les
240 fonctionnalités classiques des outils graphiques de fusion. Vous pouvez
241 voir une capture d'écran de l'utilisation de <command>kdiff3</command>
242 dans la figure <xref linkend="fig:tour-merge:kdiff3"/>. Cet outil
243 effectue une <emphasis>fusion <quote>three-way</quote></emphasis>, car il y a
244 trois différentes versions du fichier qui nous intéressent. Le fichier
245 découpe la partie supérieure de la fenêtre en trois panneaux :</para>
246 <itemizedlist>
247 <listitem><para id="x_351">À gauche on trouve la version de
248 <emphasis>base</emphasis> du fichier, soit la plus récente version
249 des deux versions qu'on souhaite fusionner.</para></listitem>
250 <listitem><para id="x_352">Au centre, il y a <quote>notre</quote>
251 version du fichier, avec le contenu que nous avons modifié.</para></listitem>
252 <listitem><para id="x_353">Sur la droite, on trouve
253 <quote>leur</quote> version du fichier, celui qui contient la
254 révision que nous souhaitons intégrer.</para>
255 </listitem></itemizedlist>
256 <para id="x_354">Dans le panneau en dessous, on trouve le
257 <emphasis>résultat</emphasis> actuel de notre fusion. Notre tâche
258 consiste donc à remplacer tous les textes en rouge,
259 qui indiquent des conflits non résolus, avec une fusion manuelle et
260 pertinente de <quote>notre</quote> version et de la <quote>leur</quote>.
261 </para>
263 <para id="x_355">Les quatre panneaux sont <emphasis>accrochés ensemble</emphasis>,
264 si nous déroulons les ascenseurs verticalement ou horizontalement dans chacun
265 d'entre eux, les autres sont mis à jour avec la section correspondante dans leurs
266 fichiers respectifs.</para>
268 <figure id="fig:tour-merge:kdiff3">
269 <title>Utiliser <command>kdiff3</command> pour fusionner les
270 différentes version d'un fichier.</title>
271 <mediaobject>
272 <imageobject>
273 <imagedata width="100%" fileref="figs/kdiff3.png"/></imageobject>
274 <textobject>
275 <phrase>XXX ajoute texte</phrase>
276 </textobject>
277 </mediaobject>
278 </figure>
280 <para id="x_357">Pour chaque portion de fichier posant problème, nous
281 pouvons choisir de résoudre le conflit en utilisant une combinaison de
282 touches depuis la version de base, la nôtre, ou la leur. Nous pouvons
283 aussi éditer manuellement les fichiers à tout moment, si c'est nécessaire.</para>
285 <para id="x_358">Il y a <emphasis>beaucoup</emphasis> d'outils de
286 fusion disponibles, bien trop pour parler de tous ici. Leurs
287 disponibilités varient selon les plateformes ainsi que leurs
288 avantages et inconvénients. La plupart sont optimisés pour
289 la fusion de fichier contenant un texte plat, certains sont spécialisés
290 dans un format de fichier précis (généralement XML).</para>
291 </sect2>
293 <sect2>
294 <title>Un exemple concret</title>
296 <para id="x_359">Dans cet exemple, nous allons reproduire la
297 modification de l'historique du fichier de la figure <xref
298 linkend="fig:tour-merge:conflict"/> ci-dessus. Commençons par créer
299 un dépôt avec une version de base de notre document.</para>
301 &interaction.tour-merge-conflict.wife;
303 <para id="x_35a">Créons un clone de ce dépôt et effectuons une
304 modification dans le fichier.</para>
306 &interaction.tour-merge-conflict.cousin;
308 <para id="x_35b">Et un autre clone, pour simuler que quelqu'un d'autre effectue une
309 modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare
310 de devoir effectuer des fusions (merges) avec vos propres travaux quand
311 vous isolez les tâches dans des dépôts distincts. En effet, vous
312 aurez alors à trouver et résoudre certains conflits).</para>
314 &interaction.tour-merge-conflict.son;
316 <para id="x_35c">Maintenant que ces deux versions différentes du même fichier sont
317 créées, nous allons configurer l'environnement de manière appropriée pour
318 exécuter notre fusion (merge).</para>
320 &interaction.tour-merge-conflict.pull;
322 <para id="x_35d">Dans cette exemple, je n'utiliserais pas la commande Mercurial
323 habituelle <command>hgmerge</command> pour effectuer la
324 fusion (merge), car il me faudrait abandonner ce joli petit exemple automatisé
325 pour utiliser un outil graphique. À la place, je vais définir la
326 variable d'environnement <envar>HGMERGE</envar> pour indiquer à
327 Mercurial d'utiliser la commande non-interactive <command>merge</command>.
328 Cette dernière est comprise dans de nombreux systèmes <quote>à la Unix</quote>.
329 Si vous exécutez cet exemple depuis votre ordinateur, ne vous
330 occupez pas de définir <envar>HGMERGE</envar>.
331 <!-- où se trouve la traduction de
332 You'll get dropped into a GUI file
333 merge tool instead, which is much preferable.)-->
334 </para>
336 &interaction.tour-merge-conflict.merge;
339 <para id="x_35f">Parce que <command>merge</command> ne peut pas résoudre
340 les modifications conflictuelles, il laisse des <emphasis>marqueurs de
341 différences</emphasis> à l'intérieur du fichier qui a des conflits,
342 indiquant clairement quelles lignes sont en conflit, et si elles
343 viennent de notre fichier ou du fichier externe.
344 </para>
346 <para id="x_360">Mercurial peut distinguer, à la manière dont la
347 commande <command>merge</command> se termine, qu'elle n'a pas été
348 capable d'effectuer la fusion (merge), alors il nous indique que nous
349 devons effectuer de nouveau cette opération. Ceci peut être très utile
350 si, par exemple, nous exécutons un outil graphique de fusion et que
351 nous le quittons sans nous rendre compte qu'il reste des conflits ou
352 simplement par erreur.</para>
354 <para id="x_361">Si la fusion (merge) automatique ou manuelle échoue,
355 il n'y a rien pour nous empêcher de <quote>corriger le tir</quote> en
356 modifiant nous-même les fichiers, et enfin effectuer le <quote>commit</quote> du
357 fichier:</para>
359 &interaction.tour-merge-conflict.commit;
361 <note>
362 <title>Où est la commande <command>hg resolve</command> ?</title>
364 <para id="x_724">La commande <command>hg resolve</command> a été
365 introduite dans la version 1.1 de Mercurial, qui a été publiée en
366 décembre 2008. Si vous utilisez une version plus anciennne de
367 Mercurial (exécutez la command <command>hg version</command> pour en
368 avoir le cœur net), cette commande ne sera pas disponible. Si votre
369 version de Mercurial est plus ancienne que la 1.1, vous devriez très
370 fortement considérer une mise à jour vers une version plus récente avant
371 d'essayer de régler des fusions complexes.</para>
372 </note>
373 </sect2>
374 </sect1>
376 <sect1 id="sec:tour-merge:fetch">
377 <title>Simplification de la séquence <quote>pull-merge-commit</quote></title>
379 <para id="x_362">La procédure pour effectuer la fusion indiquée
380 ci-dessus est simple, mais requiert le lancement de trois commandes à la
381 suite.</para>
383 <programlisting>hg pull -u
384 hg merge
385 hg commit -m 'Merged remote changes'</programlisting>
387 <para id="x_363">Lors du <quote>commit</quote> final, vous devez également saisir un
388 message, qui aura vraisemblablement assez peu d'intérêt.</para>
390 <para id="x_364">Il serait assez sympathique de pouvoir réduire le
391 nombre d'opérations nécessaire, si possible. De fait Mercurial est
392 fournit avec une extension appelée <literal role="hg-ext">fetch</literal>
393 qui fait justement cela.</para>
395 <para id="x_365">Mercurial fournit un mécanisme d'extension flexible qui permet à chacun
396 d'étendre ces fonctionnalités, tout en conservant le cœur de Mercurial
397 léger et facile à utiliser. Certaines extensions ajoutent de nouvelles
398 commandes que vous pouvez utiliser en ligne de commande, alors que
399 d'autres travaillent <quote>en coulisse</quote>, par exemple en ajoutant des
400 possibilités au serveur.</para>
402 <para id="x_366">L'extension <literal role="hg-ext">fetch</literal>
403 ajoute une nouvelle commande nommée, sans surprise, <command
404 role="hg-cmd">hg fetch</command>. Cette extension consiste en une
405 combinaison de <command role="hg-cmd">hg pull</command>, <command
406 role="hg-cmd">hg update</command> et <command role="hg-cmd">hg
407 merge</command>. Elle commence par récupérer les modifications d'un
408 autre dépôt dans le dépôt courant. Si elle trouve que les
409 modifications ajoutent une nouvelle <quote>head</quote>, elle effectue un <quote>merge</quote>,
410 et ensuite <quote>commit</quote> le résultat du <quote>merge</quote> avec un message généré
411 automatiquement. Si aucune <quote>head</quote> n'a été ajouté, elle met à jour le
412 répertoire de travail au niveau de la nouvelle révision <quote>tip</quote>.</para>
414 <para id="x_367">Activer l'extension <literal
415 role="hg-ext">fetch</literal> est facile. Modifiez votre fichier <filename
416 role="special">.hgrc</filename>, et soit allez à la section <literal
417 role="rc-extensions">extensions</literal> soit créez une section
418 <literal role="rc-extensions">extensions</literal>. Ensuite ajoutez
419 une ligne qui consiste simplement en <quote>fetch =</quote>.</para>
421 <programlisting>[extensions]
422 fetch =</programlisting>
424 <para id="x_368">(Normalement, sur la partie droite de
425 <quote><literal>=</literal></quote> devrait apparaître le chemin de
426 l'extension, mais étant donné que l'extension <literal
427 role="hg-ext">fetch</literal> fait partie de la distribution standard,
428 Mercurial sait où la trouver.) </para>
430 </sect1>
432 <sect1>
433 <title>Renommer, copier, et fusionner (merge)</title>
435 <para id="x_729">En cours de la vie d'un projet, nous allons souvent
436 vouloir changer la disposition de ses fichiers et de ses répertoires.
437 Ceci peut être aussi simple que de changer le nom d'un seul fichier,
438 et aussi compliqué que de restructurer une hiérarchie entière de fichiers
439 au sein du projet.</para>
441 <para id="x_72a">Mercurial permet de faire ce genre de modification de
442 manière fluide, à condition de l'informer de ce que nous faisons. Si
443 vous voulez renommer un ficher, vous devriez utiliser la commande
444 <command>hg rename</command><footnote>
445 <para id="x_72b">Si vous êtes un utilisateur d'Unix, vous serez content
446 de savoir que la commande <command>hg rename</command>
447 peut être abrégée en <command>hg mv</command>.</para>
448 </footnote> pour changer son nom, ainsi Mercurial peut ensuite prendre
449 la bonne décision, plus tard, en cas de fusion (merge).</para>
451 <para id="x_72c">Nous étudierons, en détail, l'utilisation de ces commandes
452 dans le chapitre <xref linkend="chap:daily.copy"/>.</para>
453 </sect1>
454 </chapter>
456 <!--
457 local variables:
458 sgml-parent-document: ("00book.xml" "book" "chapter")
459 end:
460 -->