hgbook

view en/ch03-tour-merge.xml @ 631:f7d674e6e736

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