hgbook

view fr/ch03-tour-merge.xml @ 997:c9ad85fd2f38

Fixing some XML and DTD errors to allow build of HgBook Fr
author Romain PELISSE <belaran@gmail.com>
date Sat Sep 12 20:52:03 2009 +0200 (2009-09-12)
parents 56953b292c8a
children c859c8d32838
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 rapide tour 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 iavec un gestionnaire de source 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 la fusion est une opération si commune à réaliser,
34 Mercurial la rend 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 est notre légèrement différente version du
49 dépôt.</para>
51 &interaction.tour.merge.cat2;
53 <figure id="fig:tour-merge:sep-repos">
54 <title>Historique divergent 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 'heads'</title>
76 <para id="x_341">Rappellez 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(child) ou un descendant de ce parent. Une
79 "head" est une révision qui n'a donc pas d'enfant. La révision tip
80 est donc une "head", 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 "head".</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 \textit{pull} 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 le
105 <emphasis>ID de révision (changeset ID)</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 \textit{changeset}.) Vous pouvez voir les "heads"
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 "tip"</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 "heads".</para>
134 <para id="x_723">Pour commencer une fusion (merge) entre deux "heads",
135 nous utilisons la commande <command role="hg-cmd">hg merge</command>.</para>
137 &interaction.tour.merge.merge;
139 <para id="x_347">Nous résolvons les conflits dans le fichier
140 <filename>hello.c</filename>. Ceci met à jour le répertoire de travail
141 de sorte qu'il ne contienne les modifications ne provenance des
142 <emphasis>deux</emphasis> "heads", ce qui est indiqué par la
143 la sortie de la commande <command role="hg-cmd">hg
144 parents</command> et le contenu du fichier
145 <filename>hello.c</filename>.</para>
147 &interaction.tour.merge.parents;
148 </sect2>
150 <sect2>
151 <title>Effectuer l'ajout (commit) du résultat de la fusion</title>
153 <para id="x_348">Dès l'instant où vous avez effectué une fusion
154 (merge), <command role="hg-cmd">hg parents</command> vous
155 affichera deux parents, avant que vous n'exécutiez la commande
156 <command role="hg-cmd">hg commit</command> sur le résultat de la
157 fusion.</para>
159 &interaction.tour.merge.commit;
161 <para id="x_349">Nous avons maintenant un nouveau tip, remarquer qu'il
162 contient <emphasis>à la fois</emphasis> nos anciennes "heads" et leurs
163 parents. Ce sont les mêmes révisions que nous avions affichées avec
164 la commande <command role="hg-cmd">hg parents</command>.</para>
166 &interaction.tour.merge.tip;
168 <para id="x_34a">Dans la figure <xref linkend="fig:tour-merge:merge"/>,
169 vous pouvez voir une représentation de ce qui se passe dans l'espace
170 de travail pendant la fusion, et comment ceci affecte le dépôt lors
171 du "commit". Pendant la fusion, l'espace de travail, qui a deux
172 révisions (changesets) comme parents, voit ces derniers devenir le parent
173 d'une nouvelle révision (changeset).</para>
175 <figure id="fig:tour-merge:merge">
176 <title>Working directory and repository during merge, and
177 following commit</title>
178 <mediaobject>
179 <imageobject>
180 <imagedata fileref="figs/tour-merge-merge.png"/>
181 </imageobject>
182 <textobject><phrase>XXX ajoute texte</phrase></textobject>
183 </mediaobject>
184 </figure>
186 </sect2>
187 </sect1>
189 <sect1>
190 <title>Fusionner les modifications en conflit</title>
192 <para id="x_34b">La plupart des fusions sont assez simple à réaliser, mais
193 parfois vous vous retrouverez à fusionner des fichiers où la modification
194 touche la même portion de code, au sein d'un même fichier. À moins
195 que ces modification ne soient identiques, ceci aboutira à un
196 <emphasis>conflit</emphasis>, et vous devrez décider comment réconcilier
197 les différentes modifications dans un tout cohérent.</para>
199 <figure id="fig:tour-merge:conflict">
200 <title>Modifications en conflits dans un document</title>
201 <mediaobject>
202 <imageobject><imagedata fileref="tour-merge-conflict"/></imageobject>
203 <textobject><phrase>XXX ajoute texte</phrase></textobject>
204 </mediaobject>
205 </figure>
207 <para id="x_34d">La figure <xref linkend="fig:tour-merge:conflict"/>
208 illustre un cas de modifications conflictuelles dans un document. Nous
209 avons commencé avec une version simple de ce fichier, puis nous avons
210 ajouté des modifications, pendant que quelqu'un d'autre modifiait le même
211 texte. Notre tâche dans la résolution du conflit est de décider à quoi le
212 fichier devrait ressembler.</para>
214 <para id="x_34e">Mercurial n'a pas de mécanisme interne pour gérer
215 les conflits. À la place, il exécute un programme externe appelé
216 <command>hgmerge</command>. Il s'agit d'un script shell qui est
217 embarqué par Mercurial, vous pouvez le modifier si vous le voulez.
218 Ce qu'il fait par défaut est d'essayer de trouver un des différents
219 outils de fusion qui seront probablement installés sur le système.
220 Il commence par les outils totalement automatiques, et si ils
221 échouent (parce que la résolution du conflit nécessite une
222 intervention humaine) ou si ils sont absents, le script tente
223 d'exécuter certains outils graphiques de fusion.</para>
225 <para id="x_34f">Il est aussi possible de demander à Mercurial d'exécuter
226 un autre programme ou un autre script en définissant la variable
227 d'environnement <envar>HGMERGE</envar> avec le nom
228 du programme de votre choix.</para>
230 <sect2>
231 <title>Utiliser un outil graphique de fusion</title>
233 <para id="x_350">Mon outil de fusion préféré est
234 <command>kdiff3</command>, que j'utilise ici pour illustrer les
235 fonctionnalités classiques des outils graphiques de fusion. Vous pouvez
236 voir une capture d'écran de l'utilisation de <command>kdiff3</command>
237 dans la figure <xref linkend="fig:tour-merge:kdiff3"/>. Cet outil
238 effectue une <emphasis>fusion \textit{three-way</emphasis>}, car il y a
239 trois différentes versions du fichier qui nous intéresse. Le fichier
240 découpe la partie supérieure de la fenêtre en trois panneaux:</para>
241 <itemizedlist>
242 <listitem><para id="x_351">A gauche on la version de
243 <emphasis>base</emphasis> du fichier, soit la plus récente version
244 des deux versions qu'on souhaite fusionner.</para></listitem>
245 <listitem><para id="x_352">Au centre, il y a <quote>notre</quote>
246 version du fichier, avec le contenu que nous avons modifié.</para></listitem>
247 <listitem><para id="x_353">Sur la droite, on trouve
248 <quote>leur</quote> version du fichier, celui qui contient la
249 révision que nous souhaitons intégré.</para>
250 </listitem></itemizedlist>
251 <para id="x_354">Dans le panneau en dessous, on trouve le
252 <emphasis>résultat</emphasis> actuel de notre fusion. Notre tâche
253 consiste donc à remplacement tous les textes en rouges,
254 qui indiquent des conflits non résolus, avec une fusion manuelle et
255 pertinente de <quote>notre</quote> version et de la <quote>leur</quote>.
256 </para>
258 <para id="x_355">Tous les quatre panneaux sont <emphasis>accrochés ensemble</emphasis>,
259 si nous déroulons les ascenseurs verticalement ou horizontalement dans chacun
260 d'entre eux, les autres sont mis à jour avec la section correspondante dans leurs
261 fichiers respectifs.</para>
263 <figure id="fig:tour-merge:kdiff3">
264 <title>Utiliser <command>kdiff3</command> pour fusionner les
265 différentes version d'un fichier.</title>
266 <mediaobject>
267 <imageobject>
268 <imagedata width="100%" fileref="figs/kdiff3.png"/></imageobject>
269 <textobject>
270 <phrase>XXX ajoute texte</phrase>
271 </textobject>
272 </mediaobject>
273 </figure>
275 <para id="x_357">Pour chaque portion de fichier posant problème, nous
276 pouvons choisir de résoudre le conflit en utilisant une combinaison de
277 texte depuis la version de base, la notre, ou la leur. Nous pouvons
278 aussi éditer manuellement les fichiers à tout moment, si c'est nécessaire.</para>
280 <para id="x_358">Il y a <emphasis>beaucoup</emphasis> d'outils de
281 fusion disponibles, bien trop pour en parler de tous ici. Leurs
282 disponibilités varient selon les plate formes ainsi que leurs
283 avantages et inconvénients. La plupart sont optimisé pour
284 la fusion de fichier contenant un texte plat, certains sont spécialisé
285 dans un format de fichier précis (généralement XML).</para>
286 </sect2>
288 <sect2>
289 <title>Un exemple concret</title>
291 <para id="x_359">Dans cet exemple, nous allons reproduire la
292 modification de l'historique du fichier de la figure <xref
293 linkend="fig:tour-merge:conflict"/> ci dessus. Commençons par créer
294 un dépôt avec une version de base de notre document.</para>
296 &interaction.tour-merge-conflict.wife;
298 <para id="x_35a">Créons un clone de ce dépôt et faisons une
299 modification dans le fichier.</para>
301 &interaction.tour-merge-conflict.cousin;
303 <para id="x_35b">Et un autre clone, pour simuler que quelqu'un d'autre effectue une
304 modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare
305 de devoir effectuer des fusions (merges) avec vos propres travaux quand
306 vous isolez les tâches dans des dépôts distincts. En effet, vous
307 aurez alors à trouver et résoudre certains conflits).</para>
309 &interaction.tour-merge-conflict.son;
311 <para id="x_35c">Maintenant que ces deux versions différentes du même fichier sont
312 créées, nous allons configurer l'environnement de manière appropriée pour
313 exécuter notre fusion (merge).</para>
315 &interaction.tour-merge-conflict.pull;
317 <para id="x_35d">Dans cette exemple, je n'utiliserais pas la commande Mercurial
318 habituelle <command>hgmerge</command> pour effectuer le
319 fusion (merge), car il me faudrait abandonner ce joli petit exemple automatisé
320 pour utiliser un outil graphique. À la place, je vais définir la
321 variable d'environnement <envar>HGMERGE</envar> pour indiquer à
322 Mercurial d'utiliser la commande non-interactive <command>merge</command>.
323 Cette dernière est embarquée par de nombreux systèmes <quote>à la Unix</quote>.
324 Si vous exécutez cet exemple depuis votre ordinateur, ne vous
325 occupez pas de définir <envar>HGMERGE</envar>.</para>
327 &interaction.tour-merge-conflict.merge;
330 <para id="x_35f">Parce que <command>merge</command> ne peut pas résoudre
331 les modifications conflictuelles, il laisse des <emphasis>marqueurs de
332 différences</emphasis> à l'intérieur du fichier qui a des conflits,
333 indiquant clairement quelles lignes sont en conflits, et si elles
334 viennent de notre fichier ou du fichier externe.
335 </para>
337 <para id="x_360">Mercurial peut distinguer, à la manière dont la
338 commande <command>merge</command> se termine, qu'elle n'a pas été
339 capable d'effectuer la fusion (merge), alors il nous indique que nous
340 devons effectuer de nouveau cette opération. Ceci peut être très utile
341 si, par exemple, nous exécutons un outil graphique de fusion et que
342 nous le quittons sans nous rendre compte qu'il reste des conflits ou
343 simplement par erreur.</para>
345 <para id="x_361">Si la fusion (merge) automatique ou manuelle échoue,
346 il n'y a rien pour nous empêcher de <quote>corriger le tir</quote> en
347 modifiant nous même les fichiers, et enfin effectuer le "commit" du
348 fichier:</para>
350 &interaction.tour-merge-conflict.commit;
352 <note>
353 <title>Où est la <command>hg resolve</command> ?</title>
355 <para id="x_724">La commande <command>hg resolve</command> a été
356 introduit dans la version 1.1 de Mercurial, qui a été publié en
357 décembre 2008. Si vous utilisez une version plus anciennne de
358 Mercurial (exécutez la command <command>hg version</command> pour en
359 avoir le coeur net), cette commande ne sera pas disponible. Si votre
360 version de Mercurial est plus ancienne que la 1.1, vous devriez très
361 fortement considérer une mise à jour à une version plus récente avant
362 d'essayer de régler des fusions complexes.</para>
363 </note>
364 </sect2>
365 </sect1>
367 <sect1 id="sec:tour-merge:fetch">
368 <title>Simplification de la séquence pull-merge-commit</title>
370 <para id="x_362">La procédure pour effectuer la fusion indiquée
371 ci-dessus est simple, mais requiert le lancement de trois commandes à la
372 suite.</para>
374 <programlisting>hg pull -u
375 hg merge
376 hg commit -m 'Merged remote changes'</programlisting>
378 <para id="x_363">Lors du "commit" final, vous devez également saisir un
379 message, qui aura vraisemblablement assez peu d'intérêt.</para>
381 <para id="x_364">Il serait assez sympathique de pouvoir réduire le
382 nombre d'opérations nécessaire, si possible. De fait Mercurial est
383 fourni avec une extension appelé <literal role="hg-ext">fetch</literal>
384 qui fait justement cela.</para>
386 <para id="x_365">Mercurial fourni un mécanisme d'extension flexible qui permet à chacun
387 d'étendre ces fonctionnalités, tout en conservant le cœur de Mercurial
388 léger et facile à utiliser. Certains extensions ajoutent de nouvelles
389 commandes que vous pouvez utiliser en ligne de commande, alors que
390 d'autres travaillent <quote>en coulisse,</quote> par exemple en ajoutant des
391 possibilités au serveur.</para>
393 <para id="x_366">L'extension <literal role="hg-ext">fetch</literal>
394 ajoute une nouvelle commande nommée, sans surprise, <command
395 role="hg-cmd">hg fetch</command>. Cette extension résulte en une
396 combinaison de <command role="hg-cmd">hg pull</command>, <command
397 role="hg-cmd">hg update</command> and <command role="hg-cmd">hg
398 merge</command>. Elle commence par récupérer les modifications d'un
399 autre dépôt dans le dépôt courant. Si elle trouve que les
400 modifications ajoutent une nouvelle "head", elle effectue un "merge",
401 et ensuite "commit" le résultat du "merge" avec un message généré
402 automatiquement. Si aucune "head" n'ont été ajouté, elle met à jour le
403 répertoire de travail au niveau de la nouvelle révision tip.</para>
405 <para id="x_367">Activer l'extension <literal
406 role="hg-ext">fetch</literal> est facile. Modifiez votre <filename
407 role="special">.hgrc</filename>, et soit allez à la section <literal
408 role="rc-extensions">extensions</literal> soit créer une section
409 <literal role="rc-extensions">extensions</literal>. Ensuite ajoutez
410 une ligne qui consiste simplement en <quote>\Verb+fetch =</quote>.</para>
412 <programlisting>[extensions]
413 fetch =</programlisting>
415 <para id="x_368">(Normalement, sur la partie droite de
416 <quote><literal>=</literal></quote> devrait apparaître le chemin de
417 l'extension, mais étant donné que l'extension <literal
418 role="hg-ext">fetch</literal> fait partie de la distribution standard,
419 Mercurial sait où la trouver.) </para>
421 </sect1>
423 <sect1>
424 <title>Renommer, copier, et fusionner (merge)</title>
426 <para id="x_729">En cours de la vie d'un projet, nous allons souvent
427 vouloir changer la disposition de ses fichiers et de ses répertoires.
428 Ceci peut être aussi simple que de changer le nom d'un seul fichier,
429 et aussi compliqué que de restructurer une hiérarchie entiere de fichier
430 au sein du projet.</para>
432 <para id="x_72a">Mercurial permet de faire ce genre de modification de
433 manière fluide, à condition de l'informer de ce que nous faisons. Si
434 vous voulez renommenr un ficher, vous devriez utiliser les commande
435 <command>hg rename</command><footnote>
436 <para id="x_72b">Si vous un utilisateur de Unix, vous serez content
437 de savoir que la commande <command>hg rename</command> command
438 peut être abrégée en <command>hg mv</command>.</para>
439 </footnote> pour changer son nom, ainsi Mercurial peut ensuite prendre
440 la bonne décision, plus tard, en cas de fusionv (merge).</para>
442 <para id="x_72c">Nous étudierojns en détail l'utilisation de ces commandes,
443 en détail, dans le chapitre <xref linkend="chap:daily.copy"/>.</para>
444 </sect1>
445 </chapter>
447 <!--
448 local variables:
449 sgml-parent-document: ("00book.xml" "book" "chapter")
450 end:
451 -->