rev |
line source |
belaran@953
|
1 \chapter{Un rapide tour de Mercurial: fusionner les travaux}
|
bos@95
|
2 \label{chap:tour-merge}
|
bos@94
|
3
|
Wilk@961
|
4 Nous avons maintenant étudié comment cloner un dépôt, effectuer
|
belaran@953
|
5 des changements dedans, et récupérer ou transférer depuis un
|
belaran@953
|
6 autre dépôt. La prochaine étape est donc de \emph{fusionner} les
|
belaran@953
|
7 modifications de différents dépôts.
|
belaran@953
|
8
|
belaran@953
|
9 \section{Fusionner différents travaux} %%%TODO: better translation
|
belaran@953
|
10 %%% for 'Merging streams of work' ?
|
belaran@953
|
11 La fusion\footnote{NdT: Je garde fusion mais le jargon professionnel
|
belaran@954
|
12 emploiera généralement le terme \textit{merge}.} est un aspect
|
Wilk@961
|
13 fondamental lorsqu'on travaille avec un gestionnaire de source
|
belaran@954
|
14 distribué.
|
bos@94
|
15 \begin{itemize}
|
belaran@953
|
16 \item Alice et Bob ont chacun une copie personnelle du dépôt d'un
|
belaran@953
|
17 projet sur lequel ils collaborent. Alice corrige un \textit{bug}
|
belaran@953
|
18 dans son dépôt, et Bob ajoute une nouvelle fonctionnalité dans le
|
belaran@953
|
19 sien. Ils veulent un dépôt partagé avec à la fois le correctif du
|
belaran@953
|
20 \textit{bug} et la nouvelle fonctionnalité.
|
belaran@953
|
21 \item Je travaille régulièrement sur plusieurs tâches différentes sur
|
Wilk@961
|
22 un seul projet en même temps, chacune isolée dans son propre dépôt.
|
belaran@953
|
23 Travailler ainsi signifie que je dois régulièrement fusionner une
|
belaran@953
|
24 partie de mon code avec celui des autres.
|
bos@94
|
25 \end{itemize}
|
bos@94
|
26
|
Wilk@961
|
27 Parce que la fusion est une opération si commune à réaliser,
|
belaran@954
|
28 Mercurial la rend facile. Étudions ensemble le déroulement des opérations.
|
Wilk@961
|
29 Nous commencerons encore par faire un clone d'un autre dépôt (vous voyez
|
Wilk@961
|
30 que l'on fait ça tout le temps ?) puis nous ferons quelques modifications
|
belaran@953
|
31 dessus.
|
bos@94
|
32 \interaction{tour.merge.clone}
|
belaran@953
|
33 Nous devrions avoir maintenant deux copies de \filename{hello.c} avec
|
belaran@953
|
34 des contenus différents. Les historiques de ces deux dépôts ont aussi
|
belaran@953
|
35 divergés, comme illustré dans la figure~\ref{fig:tour-merge:sep-repos}.
|
belaran@953
|
36
|
bos@94
|
37 \interaction{tour.merge.cat}
|
bos@94
|
38
|
bos@99
|
39 \begin{figure}[ht]
|
bos@99
|
40 \centering
|
bos@99
|
41 \grafix{tour-merge-sep-repos}
|
belaran@953
|
42 \caption{Historiques récent divergents des dépôts \dirname{my-hello}
|
belaran@953
|
43 et \dirname{my-new-hello}}
|
bos@99
|
44 \label{fig:tour-merge:sep-repos}
|
bos@99
|
45 \end{figure}
|
bos@99
|
46
|
belaran@953
|
47 Nous savons déjà que récupérer les modifications depuis notre dépôt
|
belaran@953
|
48 \dirname{my-hello} n'aura aucun effet sur l'espace de travail.
|
belaran@953
|
49
|
bos@94
|
50 \interaction{tour.merge.pull}
|
belaran@953
|
51
|
belaran@954
|
52 Néanmoins, la commande \hgcmd{pull} nous indique quelque chose au
|
belaran@953
|
53 sujet des ``heads''.
|
belaran@953
|
54
|
belaran@953
|
55 \subsection{\textit{Head changesets}} %%%TODO: Hard (too?) to translate
|
belaran@953
|
56
|
belaran@953
|
57 Une \textit{head}\footnote{NdT: Je garde \textit{head} que j'accorde
|
Wilk@961
|
58 au féminin comme la coutume orale l'a imposée.} est un \textit{changeset}
|
belaran@953
|
59 sans descendants, ou enfants, comme on les désigne parfois. La révision
|
belaran@953
|
60 \textit{tip} est une \textit{head}, car la dernière révision dans un dépôt
|
belaran@953
|
61 n'a aucun enfant, mais il est important de noter qu'un dépôt peut contenir
|
belaran@953
|
62 plus d'une \textit{head}.
|
bos@99
|
63
|
bos@99
|
64 \begin{figure}[ht]
|
bos@99
|
65 \centering
|
bos@99
|
66 \grafix{tour-merge-pull}
|
Wilk@961
|
67 \caption{Contenu d'un dépôt après avoir transféré le contenu du dépôt
|
belaran@953
|
68 \dirname{my-hello} dans le dépôt \dirname{my-new-hello}}
|
bos@99
|
69 \label{fig:tour-merge:pull}
|
bos@99
|
70 \end{figure}
|
bos@99
|
71
|
belaran@953
|
72 Dans la figure~\ref{fig:tour-merge:pull}, vous pouvez constater l'effet
|
belaran@953
|
73 d'un \textit{pull} depuis le dépôt \dirname{my-hello} dans le dépôt
|
belaran@953
|
74 \dirname{my-new-hello}. L'historique qui était déjà présent dans le dépôt
|
belaran@953
|
75 \dirname{my-new-hello} reste intact, mais une nouvelle révision a été
|
belaran@953
|
76 ajoutée. En vous reportant à la figure~\ref{fig:tour-merge:sep-repos},
|
belaran@953
|
77 vous pouvez voir que le \textit{\emph{changeset ID}} reste le même dans
|
belaran@953
|
78 le nouveau dépôt, mais que le \emph{numéro de révision} reste le même.
|
Wilk@961
|
79 (Ceci est un parfait exemple du fait il n'est fiable d'utiliser les
|
belaran@953
|
80 numéro de révision lorsque l'on discute d'un \textit{changeset}.) Vous
|
Wilk@961
|
81 pouvez voir les \texit{heads} présentes dans le dépôt en utilisant la
|
belaran@953
|
82 commande \hgcmd{heads}.
|
bos@94
|
83 \interaction{tour.merge.heads}
|
bos@102
|
84
|
belaran@953
|
85 \subsection{Effectuer la fusion}
|
belaran@953
|
86
|
belaran@953
|
87 Que se passe-t-il quand vous essayez d'utiliser la commande \hgcmd{update}
|
belaran@953
|
88 pour mettre à jour votre espace de travail au nouveau \textit{tip}.
|
bos@94
|
89 \interaction{tour.merge.update}
|
belaran@953
|
90 Mercurial nous prévient que la commande \hgcmd{update} n'effectuera pas
|
belaran@953
|
91 la fusion, il ne veut pas mettre à jour l'espace de travail quand il
|
belaran@953
|
92 estime que nous pourrions avoir besoin d'une fusion, à moins de lui
|
belaran@953
|
93 forcer la main. À la place, il faut utiliser la commande \hgcmd{merge}
|
belaran@953
|
94 pour fusionner les deux \textit{heads}.
|
bos@94
|
95 \interaction{tour.merge.merge}
|
bos@100
|
96
|
bos@100
|
97 \begin{figure}[ht]
|
bos@100
|
98 \centering
|
bos@100
|
99 \grafix{tour-merge-merge}
|
belaran@953
|
100 \caption{Espace de travail et dépôt lors d'une fusion, et dans le
|
belaran@953
|
101 \textit{commit} qui suit.}
|
bos@100
|
102 \label{fig:tour-merge:merge}
|
bos@100
|
103 \end{figure}
|
bos@100
|
104
|
Wilk@961
|
105 Ceci met à jour l'espace de travail de manière à ce qu'il contienne
|
belaran@954
|
106 les modifications des \emph{deux} \textit{heads}, ce qui apparaît dans
|
belaran@953
|
107 les sorties de la commande \hgcmd{parents} et le contenu de
|
belaran@953
|
108 \filename{hello.c}.
|
bos@94
|
109 \interaction{tour.merge.parents}
|
bos@102
|
110
|
belaran@954
|
111 \subsection{Effectuer le \textit{commit} du résultat de la fusion}
|
belaran@954
|
112
|
Wilk@961
|
113 Dès l'instant où vous avez effectué une fusion, \hgcmd{parents} vous
|
Wilk@961
|
114 affichera deux parents, avant que vous n'exécutiez la commande
|
belaran@954
|
115 \hgcmd{commit} sur le résultat de la fusion.
|
bos@94
|
116 \interaction{tour.merge.commit}
|
Wilk@961
|
117 Nous avons maintenant un nouveau \textit{tip}, remarquez qu'il contient
|
belaran@953
|
118 \emph{à la fois} nos anciennes \textit{heads} et leurs parents. Ce sont
|
Wilk@961
|
119 les mêmes révisions que nous avions affichées avec la commande
|
belaran@953
|
120 \hgcmd{parents}.
|
belaran@953
|
121
|
bos@94
|
122 \interaction{tour.merge.tip}
|
belaran@953
|
123 Dans la figure~\ref{fig:tour-merge:merge}, vous pouvez voir une représentation
|
belaran@953
|
124 de ce qui se passe dans l'espace de travail pendant la fusion, et comment ceci
|
belaran@953
|
125 affecte le dépôt lors du \textit{commit}. Pendant la fusion, l'espace de travail,
|
belaran@953
|
126 qui a deux \texit{changesets} comme parents, voit ces derniers devenir le parent
|
belaran@953
|
127 d'un nouveau \textit{changeset}.
|
belaran@953
|
128
|
belaran@953
|
129 \section{Fusionner les modifications en conflit}
|
belaran@953
|
130
|
Wilk@961
|
131 La plupart des fusions sont assez simples à réaliser, mais parfois
|
Wilk@961
|
132 vous vous retrouverez à fusionner des fichiers où la modification touche
|
belaran@953
|
133 la même portion de code, au sein d'un même fichier. À moins que ces
|
belaran@953
|
134 modification ne soient identiques, ceci aboutira à un \emph{conflit},
|
belaran@954
|
135 et vous devrez décider comment réconcilier les différentes modifications
|
belaran@953
|
136 dans un tout cohérent.
|
bos@103
|
137
|
bos@103
|
138 \begin{figure}[ht]
|
bos@103
|
139 \centering
|
bos@103
|
140 \grafix{tour-merge-conflict}
|
belaran@953
|
141 \caption{Modifications conflictuelles dans un document}
|
bos@103
|
142 \label{fig:tour-merge:conflict}
|
bos@103
|
143 \end{figure}
|
bos@103
|
144
|
belaran@953
|
145 La figure~\ref{fig:tour-merge:conflict} illustre un cas de modifications
|
belaran@953
|
146 conflictuelles dans un document. Nous avons commencé avec une version simple
|
Wilk@961
|
147 de ce fichier, puis nous avons ajouté des modifications, pendant que
|
Wilk@961
|
148 quelqu'un d'autre modifiait le même texte. Notre tâche dans la résolution
|
belaran@953
|
149 du conflit est de décider à quoi le fichier devrait ressembler.
|
belaran@953
|
150
|
belaran@953
|
151 Mercurial n'a pas de mécanisme interne pour gérer les conflits.
|
belaran@954
|
152 À la place, il exécute un programme externe appelé \command{hgmerge}.
|
belaran@953
|
153 Il s'agit d'un script shell qui est embarqué par Mercurial, vous
|
belaran@953
|
154 pouvez le modifier si vous le voulez. Ce qu'il fait par défaut est
|
belaran@953
|
155 d'essayer de trouver un des différents outils de fusion qui seront
|
Wilk@961
|
156 probablement installés sur le système. Il commence par les outils
|
Wilk@961
|
157 totalement automatiques, et s'ils échouent (parce que la résolution
|
Wilk@961
|
158 du conflit nécessite une intervention humaine) ou s'ils sont absents,
|
Wilk@961
|
159 le script tentera d'exécuter certains outils graphiques de fusion.
|
belaran@953
|
160
|
belaran@953
|
161 Il est aussi possible de demander à Mercurial d'exécuter un autre
|
belaran@953
|
162 programme ou un autre script au lieu de la commande \command{hgmerge},
|
belaran@954
|
163 en définissant la variable d'environnement \envar{HGMERGE} avec le nom
|
belaran@953
|
164 du programme de votre choix.
|
belaran@953
|
165
|
belaran@953
|
166 \subsection{Utiliser un outil graphique de fusion}
|
belaran@953
|
167
|
belaran@953
|
168 Mon outil de fusion préféré est \command{kdiff3}, que j'utilise ici
|
Wilk@961
|
169 pour illustrer les fonctionnalités classiques des outils graphiques
|
belaran@953
|
170 de fusion. Vous pouvez voir une capture d'écran de l'utilisation de
|
belaran@953
|
171 \command{kdiff3} dans la figure~\ref{fig:tour-merge:kdiff3}. Cet outil
|
belaran@953
|
172 effectue une \emph{fusion \textit{three-way}}, car il y a trois différentes
|
Wilk@961
|
173 versions du fichier qui nous intéressent. Le fichier découpe la partie
|
belaran@953
|
174 supérieure de la fenêtre en trois panneaux:
|
belaran@953
|
175
|
bos@103
|
176 \begin{itemize}
|
Wilk@961
|
177 \item A gauche on a la version de \emph{base} du fichier, soit ~la plus
|
Wilk@961
|
178 récente version des deux versions que l'on souhaite fusionner.
|
belaran@953
|
179 \item Au centre, il y a ``notre'' version du fichier, avec le contenu
|
belaran@953
|
180 que nous avons modifié.
|
Wilk@961
|
181 \item Sur la droite, on trouve ``leur'' version du fichier, celui qui
|
Wilk@961
|
182 contient le \textit{changeset} que nous souhaitons intégrer.
|
bos@103
|
183 \end{itemize}
|
belaran@953
|
184
|
belaran@953
|
185 Dans le panneau en dessous, on trouve le \emph{résultat} actuel de notre
|
Wilk@961
|
186 fusion. Notre tâche consiste donc à remplacement tous les textes en rouges,
|
Wilk@961
|
187 qui indiquent des conflits non résolus, avec une fusion manuelle et pertinente
|
belaran@953
|
188 de ``notre'' version et de la ``leur''.
|
belaran@953
|
189
|
Wilk@961
|
190 Tous les quatre panneaux sont \emph{accrochés ensemble}, si nous déroulons
|
belaran@953
|
191 les ascenseurs verticalement ou horizontalement dans chacun d'entre eux, les
|
Wilk@961
|
192 autres sont mis à jour avec la section correspondante dans leurs fichiers
|
Wilk@961
|
193 respectifs.
|
bos@103
|
194
|
bos@103
|
195 \begin{figure}[ht]
|
bos@103
|
196 \centering
|
bos@103
|
197 \grafix{kdiff3}
|
Wilk@961
|
198 \caption{Utilisation de \command{kdiff3} pour fusionner différentes versions
|
belaran@953
|
199 d'un fichier.}
|
bos@103
|
200 \label{fig:tour-merge:kdiff3}
|
bos@103
|
201 \end{figure}
|
bos@103
|
202
|
belaran@953
|
203 Pour chaque portion de fichier posant problème, nous pouvons choisir
|
Wilk@961
|
204 de résoudre le conflit en utilisant une combinaison
|
belaran@953
|
205 de texte depuis la version de base, la notre, ou la leur. Nous pouvons
|
Wilk@961
|
206 aussi éditer manuellement les fichiers à tout moment, si c'est
|
belaran@953
|
207 nécessaire.
|
belaran@953
|
208
|
belaran@953
|
209 Il y a \emph{beaucoup} d'outils de fusion disponibles, bien trop pour
|
belaran@954
|
210 en parler de tous ici. Leurs disponibilités varient selon les plate formes
|
belaran@954
|
211 ainsi que leurs avantages et inconvénients. La plupart sont optimisé pour
|
belaran@953
|
212 la fusion de fichier contenant un texte plat, certains sont spécialisé
|
belaran@954
|
213 dans un format de fichier précis (généralement XML).
|
belaran@954
|
214
|
Wilk@961
|
215 \subsection{Un exemple concret}
|
belaran@954
|
216
|
belaran@954
|
217 Dans cet exemple, nous allons reproduire la modification de l'historique
|
belaran@954
|
218 du fichier de la figure~\ref{fig:tour-merge:conflict} ci dessus. Commençons
|
belaran@954
|
219 par créer un dépôt avec une version de base de notre document.
|
belaran@954
|
220
|
bos@103
|
221 \interaction{tour-merge-conflict.wife}
|
belaran@954
|
222 Créons un clone de ce dépôt et faisons une modification dans le fichier.
|
bos@103
|
223 \interaction{tour-merge-conflict.cousin}
|
Wilk@961
|
224 Et un autre clone, pour simuler que quelqu'un d'autre effectue une
|
belaran@954
|
225 modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare
|
belaran@954
|
226 de devoir effectuer des \textit{merge} avec vos propres travaux quand
|
Wilk@961
|
227 vous isolez les tâches dans des dépôts distincts. En effet, vous
|
belaran@954
|
228 aurez alors à trouver et résoudre certains conflits).
|
bos@103
|
229 \interaction{tour-merge-conflict.son}
|
belaran@954
|
230 Maintenant que ces deux versions différentes du même fichier sont
|
Wilk@961
|
231 créées, nous allons configurer l'environnement de manière appropriée pour
|
Wilk@961
|
232 exécuter notre \textit{merge}.
|
bos@103
|
233 \interaction{tour-merge-conflict.pull}
|
bos@103
|
234
|
belaran@954
|
235 Dans cette exemple, je n'utiliserais pas la commande Mercurial
|
belaran@954
|
236 habituelle \command{hgmerge} pour effectuer le \textit{merge},
|
belaran@954
|
237 car il me faudrait abandonner ce joli petit exemple automatisé
|
belaran@954
|
238 pour utiliser un outil graphique. À la place, je vais définir
|
belaran@954
|
239 la variable d'environnement \envar{HGMERGE} pour indiquer à
|
belaran@954
|
240 Mercurial d'utiliser la commande non-interactive \command{merge}.
|
Wilk@961
|
241 Cette dernière est embarquée par de nombreux systèmes ``à la Unix''.
|
Wilk@961
|
242 Si vous exécutez cet exemple depuis votre ordinateur, ne vous
|
belaran@954
|
243 occupez pas de définir \envar{HGMERGE}.
|
bos@103
|
244 \interaction{tour-merge-conflict.merge}
|
belaran@954
|
245 Parce que \command{merge} ne peut pas résoudre les modifications
|
belaran@954
|
246 conflictuelles, il laisse des \emph{marqueurs de différences}
|
belaran@954
|
247 \footnote{NdT: Oui, je traduis \textit{merge markers} par un sens
|
belaran@954
|
248 inverse en Français, mais je pense vraiment que c'est plus clair
|
belaran@954
|
249 comme ça...} à l'intérieur du fichier qui a des conflits, indiquant
|
belaran@954
|
250 clairement quelles lignes sont en conflits, et si elles viennent de
|
belaran@954
|
251 notre fichier ou du fichier externe.
|
belaran@954
|
252
|
belaran@954
|
253 Mercurial peut distinguer, à la manière dont la commande \command{merge}
|
belaran@954
|
254 se termine, qu'elle n'a pas été capable d'effectuer le \textit{merge},
|
Wilk@961
|
255 alors il nous indique que nous devons effectuer de nouveau cette
|
belaran@954
|
256 opération. Ceci peut être très utile si, par exemple, nous exécutons un
|
belaran@954
|
257 outil graphique de fusion et que nous le quittons sans se rendre compte
|
belaran@954
|
258 qu'il reste des conflits ou simplement par erreur.
|
belaran@954
|
259
|
belaran@954
|
260 Si le \textit{merge} automatique ou manuel échoue, il n'y a rien pour
|
belaran@954
|
261 nous empêcher de ``corriger le tir'' en modifiant nous même les fichiers,
|
belaran@954
|
262 et enfin effectuer le \textit{commit} du fichier:
|
bos@103
|
263 \interaction{tour-merge-conflict.commit}
|
bos@103
|
264
|
Wilk@961
|
265 \section{Simplification de la séquence pull-merge-commit}
|
bos@224
|
266 \label{sec:tour-merge:fetch}
|
bos@102
|
267
|
Wilk@961
|
268 La procédure pour effectuer la fusion indiquée ci-dessus est simple,
|
Wilk@961
|
269 mais requiert le lancement de trois commandes à la suite.
|
bos@102
|
270 \begin{codesample2}
|
bos@102
|
271 hg pull
|
bos@102
|
272 hg merge
|
bos@102
|
273 hg commit -m 'Merged remote changes'
|
bos@102
|
274 \end{codesample2}
|
Wilk@961
|
275
|
Wilk@961
|
276 Lors du \textit{commit} final, vous devez également saisir un message,
|
Wilk@961
|
277 qui aura vraisemblablement assez peu d'intérêt.
|
Wilk@961
|
278
|
Wilk@961
|
279 Il serait assez sympathique de pouvoir réduire le nombre d'opérations
|
Wilk@961
|
280 nécessaire, si possible. De fait Mercurial est fourni avec une
|
Wilk@961
|
281 extension appelé \hgext{fetch} qui fait justement cela.
|
Wilk@961
|
282
|
Wilk@961
|
283 Mercurial fourni un mécanisme d'extension flexible qui permet à chacun
|
Wilk@961
|
284 d'étendre ces fonctionnalités, tout en conservant le cœur de Mercurial
|
Wilk@961
|
285 léger et facile à utiliser. Certains extensions ajoutent de nouvelles
|
Wilk@961
|
286 commandes que vous pouvez utiliser en ligne de commande, alors que
|
Wilk@961
|
287 d'autres travaillent ``en coulisse,'' par exemple en ajoutant des
|
Wilk@961
|
288 possibilités au serveur.
|
Wilk@961
|
289
|
Wilk@961
|
290 L'extension \hgext{fetch} ajoute une nouvelle commande nommée, sans
|
Wilk@961
|
291 surprise, \hgcmd{fetch}. Cette extension résulte en une combinaison
|
Wilk@961
|
292 de \hgcmd{pull}, \hgcmd{update} and \hgcmd{merge}. Elle commence par
|
Wilk@961
|
293 récupérer les modifications d'un autre dépôt dans le dépôt courant.
|
Wilk@961
|
294 Si elle trouve que les modifications ajoutent une nouvelle \textit{head},
|
Wilk@961
|
295 elle effectue un \textit{merge}, et ensuite \texit{commit} le résultat
|
Wilk@961
|
296 du \textit{merge} avec un message généré automatiquement. Si aucune
|
Wilk@961
|
297 \textit{head} n'ont été ajouté, elle met à jour le répertoire de travail
|
Wilk@961
|
298 au niveau du nouveau \textit{changeset} \textit{tip}.
|
bos@102
|
299
|
bos@102
|
300 Enabling the \hgext{fetch} extension is easy. Edit your
|
bos@102
|
301 \sfilename{.hgrc}, and either go to the \rcsection{extensions} section
|
bos@102
|
302 or create an \rcsection{extensions} section. Then add a line that
|
bos@102
|
303 simply reads ``\Verb+fetch +''.
|
Wilk@961
|
304
|
Wilk@961
|
305 Activer l'extension \hgext{fetch} est facile. Modifiez votre \sfilename{.hgrc},
|
Wilk@961
|
306 et soit allez à la section \rcsection{extensions} soit créer une
|
Wilk@961
|
307 section \rcsection{extensions}. Ensuite ajoutez une ligne qui consiste
|
Wilk@961
|
308 simplement en ``\Verb+fetch =''.
|
Wilk@961
|
309
|
bos@102
|
310 \begin{codesample2}
|
bos@102
|
311 [extensions]
|
bos@102
|
312 fetch =
|
bos@102
|
313 \end{codesample2}
|
Wilk@961
|
314
|
Wilk@961
|
315 (Normalement, sur la partie droite de ``\texttt{=}'' devrait apparaître
|
Wilk@961
|
316 le chemin de l'extension, mais étant donné que l'extension \hgext{fetch}
|
Wilk@961
|
317 fait partie de la distribution standard, Mercurial sait où la trouver.)
|
bos@102
|
318
|
bos@84
|
319 %%% Local Variables:
|
bos@84
|
320 %%% mode: latex
|
bos@84
|
321 %%% TeX-master: "00book"
|
bos@84
|
322 %%% End:
|