hgbook

annotate en/ch02-tour-merge.xml @ 600:1735c9699f92

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