Mercurial > hgbook
comparison en/ch02-tour-merge.xml @ 749:7e7c47481e4f
Oops, this is the real merge for my hg's oddity
author | Dongsheng Song <dongsheng.song@gmail.com> |
---|---|
date | Fri, 20 Mar 2009 16:43:35 +0800 |
parents | en/ch03-tour-merge.xml@d0160b0b1a9e |
children | 1c13ed2130a7 |
comparison
equal
deleted
inserted
replaced
748:d13c7c706a58 | 749:7e7c47481e4f |
---|---|
1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> | |
2 | |
3 <chapter id="chap.tour-merge"> | |
4 <?dbhtml filename="a-tour-of-mercurial-merging-work.html"?> | |
5 <title>A tour of Mercurial: merging work</title> | |
6 | |
7 <para>We've now covered cloning a repository, making changes in a | |
8 repository, and pulling or pushing changes from one repository | |
9 into another. Our next step is <emphasis>merging</emphasis> | |
10 changes from separate repositories.</para> | |
11 | |
12 <sect1> | |
13 <title>Merging streams of work</title> | |
14 | |
15 <para>Merging is a fundamental part of working with a distributed | |
16 revision control tool.</para> | |
17 <itemizedlist> | |
18 <listitem><para>Alice and Bob each have a personal copy of a | |
19 repository for a project they're collaborating on. Alice | |
20 fixes a bug in her repository; Bob adds a new feature in | |
21 his. They want the shared repository to contain both the | |
22 bug fix and the new feature.</para> | |
23 </listitem> | |
24 <listitem><para>I frequently work on several different tasks for | |
25 a single project at once, each safely isolated in its own | |
26 repository. Working this way means that I often need to | |
27 merge one piece of my own work with another.</para> | |
28 </listitem></itemizedlist> | |
29 | |
30 <para>Because merging is such a common thing to need to do, | |
31 Mercurial makes it easy. Let's walk through the process. We'll | |
32 begin by cloning yet another repository (see how often they | |
33 spring up?) and making a change in it.</para> | |
34 | |
35 &interaction.tour.merge.clone; | |
36 | |
37 <para>We should now have two copies of | |
38 <filename>hello.c</filename> with different contents. The | |
39 histories of the two repositories have also diverged, as | |
40 illustrated in figure <xref endterm="fig.tour-merge.sep-repos.caption" | |
41 linkend="fig.tour-merge.sep-repos"/>.</para> | |
42 | |
43 &interaction.tour.merge.cat; | |
44 | |
45 <informalfigure id="fig.tour-merge.sep-repos"> | |
46 <mediaobject> | |
47 <imageobject><imagedata fileref="images/tour-merge-sep-repos.png"/></imageobject> | |
48 <textobject><phrase>XXX add text</phrase></textobject> | |
49 <caption><para id="fig.tour-merge.sep-repos.caption">Divergent recent | |
50 histories of the <filename | |
51 class="directory">my-hello</filename> and <filename | |
52 class="directory">my-new-hello</filename> | |
53 repositories</para></caption> | |
54 </mediaobject> | |
55 </informalfigure> | |
56 | |
57 <para>We already know that pulling changes from our <filename | |
58 class="directory">my-hello</filename> repository will have no | |
59 effect on the working directory.</para> | |
60 | |
61 &interaction.tour.merge.pull; | |
62 | |
63 <para>However, the <command role="hg-cmd">hg pull</command> | |
64 command says something about <quote>heads</quote>.</para> | |
65 | |
66 <sect2> | |
67 <title>Head changesets</title> | |
68 | |
69 <para>A head is a change that has no descendants, or children, | |
70 as they're also known. The tip revision is thus a head, | |
71 because the newest revision in a repository doesn't have any | |
72 children, but a repository can contain more than one | |
73 head.</para> | |
74 | |
75 <informalfigure id="fig.tour-merge.pull"> | |
76 <mediaobject> | |
77 <imageobject><imagedata fileref="images/tour-merge-pull.png"/></imageobject> | |
78 <textobject><phrase>XXX add text</phrase></textobject> | |
79 <caption><para id="fig.tour-merge.pull.caption">Repository contents after | |
80 pulling from <filename class="directory">my-hello</filename> into | |
81 <filename class="directory">my-new-hello</filename></para></caption> | |
82 </mediaobject> | |
83 </informalfigure> | |
84 | |
85 <para>In figure <xref endterm="fig.tour-merge.pull.caption" | |
86 linkend="fig.tour-merge.pull"/>, you can | |
87 see the effect of the pull from <filename | |
88 class="directory">my-hello</filename> into <filename | |
89 class="directory">my-new-hello</filename>. The history that | |
90 was already present in <filename | |
91 class="directory">my-new-hello</filename> is untouched, but | |
92 a new revision has been added. By referring to figure <xref | |
93 endterm="fig.tour-merge.sep-repos.caption" | |
94 linkend="fig.tour-merge.sep-repos"/>, we can see that the | |
95 <emphasis>changeset ID</emphasis> remains the same in the new | |
96 repository, but the <emphasis>revision number</emphasis> has | |
97 changed. (This, incidentally, is a fine example of why it's | |
98 not safe to use revision numbers when discussing changesets.) | |
99 We can view the heads in a repository using the <command | |
100 role="hg-cmd">hg heads</command> command.</para> | |
101 | |
102 &interaction.tour.merge.heads; | |
103 | |
104 </sect2> | |
105 <sect2> | |
106 <title>Performing the merge</title> | |
107 | |
108 <para>What happens if we try to use the normal <command | |
109 role="hg-cmd">hg update</command> command to update to the | |
110 new tip?</para> | |
111 | |
112 &interaction.tour.merge.update; | |
113 | |
114 <para>Mercurial is telling us that the <command role="hg-cmd">hg | |
115 update</command> command won't do a merge; it won't update | |
116 the working directory when it thinks we might be wanting to do | |
117 a merge, unless we force it to do so. Instead, we use the | |
118 <command role="hg-cmd">hg merge</command> command to merge the | |
119 two heads.</para> | |
120 | |
121 &interaction.tour.merge.merge; | |
122 | |
123 <informalfigure id="fig.tour-merge.merge"> | |
124 <mediaobject> | |
125 <imageobject><imagedata fileref="images/tour-merge-merge.png"/></imageobject> | |
126 <textobject><phrase>XXX add text</phrase></textobject> | |
127 <caption><para id="fig.tour-merge.merge.caption">Working directory and | |
128 repository during merge, and following commit</para></caption> | |
129 </mediaobject> | |
130 </informalfigure> | |
131 | |
132 <para>This updates the working directory so that it contains | |
133 changes from <emphasis>both</emphasis> heads, which is | |
134 reflected in both the output of <command role="hg-cmd">hg | |
135 parents</command> and the contents of | |
136 <filename>hello.c</filename>.</para> | |
137 | |
138 &interaction.tour.merge.parents; | |
139 | |
140 </sect2> | |
141 <sect2> | |
142 <title>Committing the results of the merge</title> | |
143 | |
144 <para>Whenever we've done a merge, <command role="hg-cmd">hg | |
145 parents</command> will display two parents until we <command | |
146 role="hg-cmd">hg commit</command> the results of the | |
147 merge.</para> | |
148 | |
149 &interaction.tour.merge.commit; | |
150 | |
151 <para>We now have a new tip revision; notice that it has | |
152 <emphasis>both</emphasis> of our former heads as its parents. | |
153 These are the same revisions that were previously displayed by | |
154 <command role="hg-cmd">hg parents</command>.</para> | |
155 | |
156 &interaction.tour.merge.tip; | |
157 | |
158 <para>In figure <xref endterm="fig.tour-merge.merge.caption" | |
159 linkend="fig.tour-merge.merge"/>, you can see a | |
160 representation of what happens to the working directory during | |
161 the merge, and how this affects the repository when the commit | |
162 happens. During the merge, the working directory has two | |
163 parent changesets, and these become the parents of the new | |
164 changeset.</para> | |
165 | |
166 </sect2> | |
167 </sect1> | |
168 <sect1> | |
169 <title>Merging conflicting changes</title> | |
170 | |
171 <para>Most merges are simple affairs, but sometimes you'll find | |
172 yourself merging changes where each modifies the same portions | |
173 of the same files. Unless both modifications are identical, | |
174 this results in a <emphasis>conflict</emphasis>, where you have | |
175 to decide how to reconcile the different changes into something | |
176 coherent.</para> | |
177 | |
178 <informalfigure id="fig.tour-merge.conflict"> | |
179 <mediaobject> | |
180 <imageobject><imagedata fileref="images/tour-merge-conflict.png"/> | |
181 </imageobject> | |
182 <textobject><phrase>XXX add text</phrase></textobject> | |
183 <caption><para id="fig.tour-merge.conflict.caption">Conflicting | |
184 changes to a document</para></caption> | |
185 </mediaobject> | |
186 </informalfigure> | |
187 | |
188 <para>Figure <xref endterm="fig.tour-merge.conflict.caption" | |
189 linkend="fig.tour-merge.conflict"/> illustrates | |
190 an instance of two conflicting changes to a document. We | |
191 started with a single version of the file; then we made some | |
192 changes; while someone else made different changes to the same | |
193 text. Our task in resolving the conflicting changes is to | |
194 decide what the file should look like.</para> | |
195 | |
196 <para>Mercurial doesn't have a built-in facility for handling | |
197 conflicts. Instead, it runs an external program called | |
198 <command>hgmerge</command>. This is a shell script that is | |
199 bundled with Mercurial; you can change it to behave however you | |
200 please. What it does by default is try to find one of several | |
201 different merging tools that are likely to be installed on your | |
202 system. It first tries a few fully automatic merging tools; if | |
203 these don't succeed (because the resolution process requires | |
204 human guidance) or aren't present, the script tries a few | |
205 different graphical merging tools.</para> | |
206 | |
207 <para>It's also possible to get Mercurial to run another program | |
208 or script instead of <command>hgmerge</command>, by setting the | |
209 <envar>HGMERGE</envar> environment variable to the name of your | |
210 preferred program.</para> | |
211 | |
212 <sect2> | |
213 <title>Using a graphical merge tool</title> | |
214 | |
215 <para>My preferred graphical merge tool is | |
216 <command>kdiff3</command>, which I'll use to describe the | |
217 features that are common to graphical file merging tools. You | |
218 can see a screenshot of <command>kdiff3</command> in action in | |
219 figure <xref endterm="fig.tour-merge.kdiff3.caption" | |
220 linkend="fig.tour-merge.kdiff3"/>. The kind of | |
221 merge it is performing is called a <emphasis>three-way | |
222 merge</emphasis>, because there are three different versions | |
223 of the file of interest to us. The tool thus splits the upper | |
224 portion of the window into three panes:</para> | |
225 <itemizedlist> | |
226 <listitem><para>At the left is the <emphasis>base</emphasis> | |
227 version of the file, i.e. the most recent version from | |
228 which the two versions we're trying to merge are | |
229 descended.</para> | |
230 </listitem> | |
231 <listitem><para>In the middle is <quote>our</quote> version of | |
232 the file, with the contents that we modified.</para> | |
233 </listitem> | |
234 <listitem><para>On the right is <quote>their</quote> version | |
235 of the file, the one that from the changeset that we're | |
236 trying to merge with.</para> | |
237 </listitem></itemizedlist> | |
238 <para>In the pane below these is the current | |
239 <emphasis>result</emphasis> of the merge. Our task is to | |
240 replace all of the red text, which indicates unresolved | |
241 conflicts, with some sensible merger of the | |
242 <quote>ours</quote> and <quote>theirs</quote> versions of the | |
243 file.</para> | |
244 | |
245 <para>All four of these panes are <emphasis>locked | |
246 together</emphasis>; if we scroll vertically or horizontally | |
247 in any of them, the others are updated to display the | |
248 corresponding sections of their respective files.</para> | |
249 | |
250 <informalfigure id="fig.tour-merge.kdiff3"> | |
251 <mediaobject> | |
252 <imageobject><imagedata width="100%" fileref="images/kdiff3.png"/> | |
253 </imageobject> | |
254 <textobject><phrase>XXX add text</phrase></textobject> | |
255 <caption><para id="fig.tour-merge.kdiff3.caption">Using | |
256 <command>kdiff3</command> to merge versions of a file</para> | |
257 </caption> | |
258 </mediaobject> | |
259 </informalfigure> | |
260 | |
261 <para>For each conflicting portion of the file, we can choose to | |
262 resolve the conflict using some combination of text from the | |
263 base version, ours, or theirs. We can also manually edit the | |
264 merged file at any time, in case we need to make further | |
265 modifications.</para> | |
266 | |
267 <para>There are <emphasis>many</emphasis> file merging tools | |
268 available, too many to cover here. They vary in which | |
269 platforms they are available for, and in their particular | |
270 strengths and weaknesses. Most are tuned for merging files | |
271 containing plain text, while a few are aimed at specialised | |
272 file formats (generally XML).</para> | |
273 | |
274 </sect2> | |
275 <sect2> | |
276 <title>A worked example</title> | |
277 | |
278 <para>In this example, we will reproduce the file modification | |
279 history of figure <xref endterm="fig.tour-merge.conflict.caption" | |
280 linkend="fig.tour-merge.conflict"/> | |
281 above. Let's begin by creating a repository with a base | |
282 version of our document.</para> | |
283 | |
284 &interaction.tour-merge-conflict.wife; | |
285 | |
286 <para>We'll clone the repository and make a change to the | |
287 file.</para> | |
288 | |
289 &interaction.tour-merge-conflict.cousin; | |
290 | |
291 <para>And another clone, to simulate someone else making a | |
292 change to the file. (This hints at the idea that it's not all | |
293 that unusual to merge with yourself when you isolate tasks in | |
294 separate repositories, and indeed to find and resolve | |
295 conflicts while doing so.)</para> | |
296 | |
297 &interaction.tour-merge-conflict.son; | |
298 | |
299 <para>Having created two | |
300 different versions of the file, we'll set up an environment | |
301 suitable for running our merge.</para> | |
302 | |
303 &interaction.tour-merge-conflict.pull; | |
304 | |
305 <para>In this example, I won't use Mercurial's normal | |
306 <command>hgmerge</command> program to do the merge, because it | |
307 would drop my nice automated example-running tool into a | |
308 graphical user interface. Instead, I'll set | |
309 <envar>HGMERGE</envar> to tell Mercurial to use the | |
310 non-interactive <command>merge</command> command. This is | |
311 bundled with many Unix-like systems. If you're following this | |
312 example on your computer, don't bother setting | |
313 <envar>HGMERGE</envar>.</para> | |
314 | |
315 <para><emphasis role="bold">XXX FIX THIS | |
316 EXAMPLE.</emphasis></para> | |
317 | |
318 &interaction.tour-merge-conflict.merge; | |
319 | |
320 <para>Because <command>merge</command> can't resolve the | |
321 conflicting changes, it leaves <emphasis>merge | |
322 markers</emphasis> inside the file that has conflicts, | |
323 indicating which lines have conflicts, and whether they came | |
324 from our version of the file or theirs.</para> | |
325 | |
326 <para>Mercurial can tell from the way <command>merge</command> | |
327 exits that it wasn't able to merge successfully, so it tells | |
328 us what commands we'll need to run if we want to redo the | |
329 merging operation. This could be useful if, for example, we | |
330 were running a graphical merge tool and quit because we were | |
331 confused or realised we had made a mistake.</para> | |
332 | |
333 <para>If automatic or manual merges fail, there's nothing to | |
334 prevent us from <quote>fixing up</quote> the affected files | |
335 ourselves, and committing the results of our merge:</para> | |
336 | |
337 &interaction.tour-merge-conflict.commit; | |
338 | |
339 </sect2> | |
340 </sect1> | |
341 <sect1 id="sec.tour-merge.fetch"> | |
342 <title>Simplifying the pull-merge-commit sequence</title> | |
343 | |
344 <para>The process of merging changes as outlined above is | |
345 straightforward, but requires running three commands in | |
346 sequence.</para> | |
347 <programlisting>hg pull | |
348 hg merge | |
349 hg commit -m 'Merged remote changes'</programlisting> | |
350 <para>In the case of the final commit, you also need to enter a | |
351 commit message, which is almost always going to be a piece of | |
352 uninteresting <quote>boilerplate</quote> text.</para> | |
353 | |
354 <para>It would be nice to reduce the number of steps needed, if | |
355 this were possible. Indeed, Mercurial is distributed with an | |
356 extension called <literal role="hg-ext">fetch</literal> that | |
357 does just this.</para> | |
358 | |
359 <para>Mercurial provides a flexible extension mechanism that lets | |
360 people extend its functionality, while keeping the core of | |
361 Mercurial small and easy to deal with. Some extensions add new | |
362 commands that you can use from the command line, while others | |
363 work <quote>behind the scenes,</quote> for example adding | |
364 capabilities to the server.</para> | |
365 | |
366 <para>The <literal role="hg-ext">fetch</literal> extension adds a | |
367 new command called, not surprisingly, <command role="hg-cmd">hg | |
368 fetch</command>. This extension acts as a combination of | |
369 <command role="hg-cmd">hg pull</command>, <command | |
370 role="hg-cmd">hg update</command> and <command | |
371 role="hg-cmd">hg merge</command>. It begins by pulling | |
372 changes from another repository into the current repository. If | |
373 it finds that the changes added a new head to the repository, it | |
374 begins a merge, then commits the result of the merge with an | |
375 automatically-generated commit message. If no new heads were | |
376 added, it updates the working directory to the new tip | |
377 changeset.</para> | |
378 | |
379 <para>Enabling the <literal role="hg-ext">fetch</literal> | |
380 extension is easy. Edit your <filename | |
381 role="special">.hgrc</filename>, and either go to the <literal | |
382 role="rc-extensions">extensions</literal> section or create an | |
383 <literal role="rc-extensions">extensions</literal> section. Then | |
384 add a line that simply reads <quote><literal>fetch | |
385 </literal></quote>.</para> | |
386 <programlisting>[extensions] | |
387 fetch =</programlisting> | |
388 <para>(Normally, on the right-hand side of the | |
389 <quote><literal>=</literal></quote> would appear the location of | |
390 the extension, but since the <literal | |
391 role="hg-ext">fetch</literal> extension is in the standard | |
392 distribution, Mercurial knows where to search for it.)</para> | |
393 | |
394 </sect1> | |
395 </chapter> | |
396 | |
397 <!-- | |
398 local variables: | |
399 sgml-parent-document: ("00book.xml" "book" "chapter") | |
400 end: | |
401 --> |