hgbook

diff en/ch03-tour-merge.xml @ 559:b90b024729f1

WIP DocBook snapshot that all compiles. Mirabile dictu!
author Bryan O'Sullivan <bos@serpentine.com>
date Wed Feb 18 00:22:09 2009 -0800 (2009-02-18)
parents en/ch03-tour-merge.tex@f72b7e6cbe90
children 8fcd44708f41
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/en/ch03-tour-merge.xml	Wed Feb 18 00:22:09 2009 -0800
     1.3 @@ -0,0 +1,394 @@
     1.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
     1.5 +
     1.6 +<chapter id="chap:tour-merge">
     1.7 +  <title>A tour of Mercurial: merging work</title>
     1.8 +
     1.9 +  <para>We've now covered cloning a repository, making changes in a
    1.10 +    repository, and pulling or pushing changes from one repository
    1.11 +    into another.  Our next step is <emphasis>merging</emphasis>
    1.12 +    changes from separate repositories.</para>
    1.13 +
    1.14 +  <sect1>
    1.15 +    <title>Merging streams of work</title>
    1.16 +
    1.17 +    <para>Merging is a fundamental part of working with a distributed
    1.18 +      revision control tool.</para>
    1.19 +    <itemizedlist>
    1.20 +      <listitem><para>Alice and Bob each have a personal copy of a
    1.21 +	  repository for a project they're collaborating on.  Alice
    1.22 +	  fixes a bug in her repository; Bob adds a new feature in
    1.23 +	  his.  They want the shared repository to contain both the
    1.24 +	  bug fix and the new feature.</para>
    1.25 +      </listitem>
    1.26 +      <listitem><para>I frequently work on several different tasks for
    1.27 +	  a single project at once, each safely isolated in its own
    1.28 +	  repository. Working this way means that I often need to
    1.29 +	  merge one piece of my own work with another.</para>
    1.30 +      </listitem></itemizedlist>
    1.31 +
    1.32 +    <para>Because merging is such a common thing to need to do,
    1.33 +      Mercurial makes it easy.  Let's walk through the process.  We'll
    1.34 +      begin by cloning yet another repository (see how often they
    1.35 +      spring up?) and making a change in it.</para>
    1.36 +
    1.37 +    <!-- &interaction.tour.merge.clone; -->
    1.38 +
    1.39 +    <para>We should now have two copies of
    1.40 +      <filename>hello.c</filename> with different contents.  The
    1.41 +      histories of the two repositories have also diverged, as
    1.42 +      illustrated in figure <xref
    1.43 +	linkend="fig:tour-merge:sep-repos"/>.</para>
    1.44 +
    1.45 +    <!-- &interaction.tour.merge.cat; -->
    1.46 +
    1.47 +    <informalfigure id="fig:tour-merge:sep-repos">
    1.48 +      <mediaobject>
    1.49 +	<imageobject><imagedata fileref="tour-merge-sep-repos"/></imageobject>
    1.50 +	<textobject><phrase>XXX add text</phrase></textobject>
    1.51 +	<caption><para>Divergent recent histories of the <filename
    1.52 +	      class="directory">my-hello</filename> and <filename
    1.53 +	      class="directory">my-new-hello</filename>
    1.54 +	    repositories</para></caption>
    1.55 +      </mediaobject>
    1.56 +    </informalfigure>
    1.57 +
    1.58 +    <para>We already know that pulling changes from our <filename
    1.59 +	class="directory">my-hello</filename> repository will have no
    1.60 +      effect on the working directory.</para>
    1.61 +
    1.62 +    <!-- &interaction.tour.merge.pull; -->
    1.63 +
    1.64 +    <para>However, the <command role="hg-cmd">hg pull</command>
    1.65 +      command says something about <quote>heads</quote>.</para>
    1.66 +
    1.67 +    <sect2>
    1.68 +      <title>Head changesets</title>
    1.69 +
    1.70 +      <para>A head is a change that has no descendants, or children,
    1.71 +	as they're also known.  The tip revision is thus a head,
    1.72 +	because the newest revision in a repository doesn't have any
    1.73 +	children, but a repository can contain more than one
    1.74 +	head.</para>
    1.75 +
    1.76 +      <informalfigure id="fig:tour-merge:pull">
    1.77 +	<mediaobject><imageobject><imagedata
    1.78 +				    fileref="tour-merge-pull"/></imageobject><textobject><phrase>XXX 
    1.79 +	      add text</phrase></textobject>
    1.80 +	  <caption><para>Repository contents after pulling from
    1.81 +	      <filename class="directory">my-hello</filename> into
    1.82 +	      <filename
    1.83 +		class="directory">my-new-hello</filename></para></caption>
    1.84 +	</mediaobject>
    1.85 +      </informalfigure>
    1.86 +
    1.87 +      <para>In figure <xref linkend="fig:tour-merge:pull"/>, you can
    1.88 +	see the effect of the pull from <filename
    1.89 +	  class="directory">my-hello</filename> into <filename
    1.90 +	  class="directory">my-new-hello</filename>.  The history that
    1.91 +	was already present in <filename
    1.92 +	  class="directory">my-new-hello</filename> is untouched, but
    1.93 +	a new revision has been added.  By referring to figure <xref
    1.94 +	  linkend="fig:tour-merge:sep-repos"/>, we can see that the
    1.95 +	<emphasis>changeset ID</emphasis> remains the same in the new
    1.96 +	repository, but the <emphasis>revision number</emphasis> has
    1.97 +	changed.  (This, incidentally, is a fine example of why it's
    1.98 +	not safe to use revision numbers when discussing changesets.)
    1.99 +	We can view the heads in a repository using the <command
   1.100 +	  role="hg-cmd">hg heads</command> command.</para>
   1.101 +
   1.102 +      <!-- &interaction.tour.merge.heads; -->
   1.103 +
   1.104 +    </sect2>
   1.105 +    <sect2>
   1.106 +      <title>Performing the merge</title>
   1.107 +
   1.108 +      <para>What happens if we try to use the normal <command
   1.109 +	  role="hg-cmd">hg update</command> command to update to the
   1.110 +	new tip?</para>
   1.111 +
   1.112 +      <!-- &interaction.tour.merge.update; -->
   1.113 +
   1.114 +      <para>Mercurial is telling us that the <command role="hg-cmd">hg
   1.115 +	  update</command> command won't do a merge; it won't update
   1.116 +	the working directory when it thinks we might be wanting to do
   1.117 +	a merge, unless we force it to do so.  Instead, we use the
   1.118 +	<command role="hg-cmd">hg merge</command> command to merge the
   1.119 +	two heads.</para>
   1.120 +
   1.121 +      <!-- &interaction.tour.merge.merge; -->
   1.122 +
   1.123 +      <informalfigure id="fig:tour-merge:merge">
   1.124 +
   1.125 +	<mediaobject><imageobject><imagedata
   1.126 +				    fileref="tour-merge-merge"/></imageobject><textobject><phrase>XXX 
   1.127 +	      add text</phrase></textobject>
   1.128 +	  <caption><para>Working directory and repository during
   1.129 +	      merge, and following commit</para></caption>
   1.130 +	</mediaobject>
   1.131 +      </informalfigure>
   1.132 +
   1.133 +      <para>This updates the working directory so that it contains
   1.134 +	changes from <emphasis>both</emphasis> heads, which is
   1.135 +	reflected in both the output of <command role="hg-cmd">hg
   1.136 +	  parents</command> and the contents of
   1.137 +	<filename>hello.c</filename>.</para>
   1.138 +
   1.139 +      <!-- &interaction.tour.merge.parents; -->
   1.140 +
   1.141 +    </sect2>
   1.142 +    <sect2>
   1.143 +      <title>Committing the results of the merge</title>
   1.144 +
   1.145 +      <para>Whenever we've done a merge, <command role="hg-cmd">hg
   1.146 +	  parents</command> will display two parents until we <command
   1.147 +	  role="hg-cmd">hg commit</command> the results of the
   1.148 +	  merge.</para>
   1.149 +
   1.150 +	<!-- &interaction.tour.merge.commit; -->
   1.151 +
   1.152 +      <para>We now have a new tip revision; notice that it has
   1.153 +	<emphasis>both</emphasis> of our former heads as its parents.
   1.154 +	These are the same revisions that were previously displayed by
   1.155 +	<command role="hg-cmd">hg parents</command>.</para>
   1.156 +
   1.157 +      <!-- &interaction.tour.merge.tip; -->
   1.158 +
   1.159 +      <para>In figure <xref
   1.160 +	  linkend="fig:tour-merge:merge"/>, you can see a
   1.161 +	representation of what happens to the working directory during
   1.162 +	the merge, and how this affects the repository when the commit
   1.163 +	happens.  During the merge, the working directory has two
   1.164 +	parent changesets, and these become the parents of the new
   1.165 +	changeset.</para>
   1.166 +
   1.167 +    </sect2>
   1.168 +  </sect1>
   1.169 +  <sect1>
   1.170 +    <title>Merging conflicting changes</title>
   1.171 +
   1.172 +    <para>Most merges are simple affairs, but sometimes you'll find
   1.173 +      yourself merging changes where each modifies the same portions
   1.174 +      of the same files.  Unless both modifications are identical,
   1.175 +      this results in a <emphasis>conflict</emphasis>, where you have
   1.176 +      to decide how to reconcile the different changes into something
   1.177 +      coherent.</para>
   1.178 +
   1.179 +    <informalfigure>
   1.180 +
   1.181 +      <mediaobject id="fig:tour-merge:conflict">
   1.182 +	<imageobject><imagedata fileref="tour-merge-conflict"/></imageobject>
   1.183 +	<textobject><phrase>XXX add text</phrase></textobject>
   1.184 +	<caption><para>Conflicting changes to a
   1.185 +	    document</para></caption>      </mediaobject>
   1.186 +    </informalfigure>
   1.187 +
   1.188 +    <para>Figure <xref linkend="fig:tour-merge:conflict"/> illustrates
   1.189 +      an instance of two conflicting changes to a document.  We
   1.190 +      started with a single version of the file; then we made some
   1.191 +      changes; while someone else made different changes to the same
   1.192 +      text.  Our task in resolving the conflicting changes is to
   1.193 +      decide what the file should look like.</para>
   1.194 +
   1.195 +    <para>Mercurial doesn't have a built-in facility for handling
   1.196 +      conflicts. Instead, it runs an external program called
   1.197 +      <command>hgmerge</command>.  This is a shell script that is
   1.198 +      bundled with Mercurial; you can change it to behave however you
   1.199 +      please.  What it does by default is try to find one of several
   1.200 +      different merging tools that are likely to be installed on your
   1.201 +      system.  It first tries a few fully automatic merging tools; if
   1.202 +      these don't succeed (because the resolution process requires
   1.203 +      human guidance) or aren't present, the script tries a few
   1.204 +      different graphical merging tools.</para>
   1.205 +
   1.206 +    <para>It's also possible to get Mercurial to run another program
   1.207 +      or script instead of <command>hgmerge</command>, by setting the
   1.208 +      <envar>HGMERGE</envar> environment variable to the name of your
   1.209 +      preferred program.</para>
   1.210 +
   1.211 +    <sect2>
   1.212 +      <title>Using a graphical merge tool</title>
   1.213 +
   1.214 +      <para>My preferred graphical merge tool is
   1.215 +	<command>kdiff3</command>, which I'll use to describe the
   1.216 +	features that are common to graphical file merging tools.  You
   1.217 +	can see a screenshot of <command>kdiff3</command> in action in
   1.218 +	figure <xref linkend="fig:tour-merge:kdiff3"/>.  The kind of
   1.219 +	merge it is performing is called a <emphasis>three-way
   1.220 +	  merge</emphasis>, because there are three different versions
   1.221 +	of the file of interest to us.  The tool thus splits the upper
   1.222 +	portion of the window into three panes:</para>
   1.223 +      <itemizedlist>
   1.224 +	<listitem><para>At the left is the <emphasis>base</emphasis>
   1.225 +	    version of the file, i.e. the most recent version from
   1.226 +	    which the two versions we're trying to merge are
   1.227 +	    descended.</para>
   1.228 +	</listitem>
   1.229 +	<listitem><para>In the middle is <quote>our</quote> version of
   1.230 +	    the file, with the contents that we modified.</para>
   1.231 +	</listitem>
   1.232 +	<listitem><para>On the right is <quote>their</quote> version
   1.233 +	    of the file, the one that from the changeset that we're
   1.234 +	    trying to merge with.</para>
   1.235 +	</listitem></itemizedlist>
   1.236 +      <para>In the pane below these is the current
   1.237 +	<emphasis>result</emphasis> of the merge. Our task is to
   1.238 +	replace all of the red text, which indicates unresolved
   1.239 +	conflicts, with some sensible merger of the
   1.240 +	<quote>ours</quote> and <quote>theirs</quote> versions of the
   1.241 +	file.</para>
   1.242 +
   1.243 +      <para>All four of these panes are <emphasis>locked
   1.244 +	  together</emphasis>; if we scroll vertically or horizontally
   1.245 +	in any of them, the others are updated to display the
   1.246 +	corresponding sections of their respective files.</para>
   1.247 +
   1.248 +      <informalfigure id="fig:tour-merge:kdiff3">
   1.249 +	<mediaobject><imageobject><imagedata
   1.250 +				    fileref="kdiff3"/></imageobject><textobject><phrase>XXX 
   1.251 +	      add text</phrase></textobject>
   1.252 +	  <caption><para>Using <command>kdiff3</command> to merge
   1.253 +	      versions of a file</para></caption>
   1.254 +	</mediaobject>
   1.255 +      </informalfigure>
   1.256 +
   1.257 +      <para>For each conflicting portion of the file, we can choose to
   1.258 +	resolve the conflict using some combination of text from the
   1.259 +	base version, ours, or theirs.  We can also manually edit the
   1.260 +	merged file at any time, in case we need to make further
   1.261 +	modifications.</para>
   1.262 +
   1.263 +      <para>There are <emphasis>many</emphasis> file merging tools
   1.264 +	available, too many to cover here.  They vary in which
   1.265 +	platforms they are available for, and in their particular
   1.266 +	strengths and weaknesses.  Most are tuned for merging files
   1.267 +	containing plain text, while a few are aimed at specialised
   1.268 +	file formats (generally XML).</para>
   1.269 +
   1.270 +    </sect2>
   1.271 +    <sect2>
   1.272 +      <title>A worked example</title>
   1.273 +
   1.274 +      <para>In this example, we will reproduce the file modification
   1.275 +	history of figure <xref linkend="fig:tour-merge:conflict"/>
   1.276 +	above.  Let's begin by creating a repository with a base
   1.277 +	version of our document.</para>
   1.278 +
   1.279 +      <!-- &interaction.tour-merge-conflict.wife; -->
   1.280 +
   1.281 +      <para>We'll clone the repository and make a change to the
   1.282 +	file.</para>
   1.283 +
   1.284 +      <!-- &interaction.tour-merge-conflict.cousin; -->
   1.285 +
   1.286 +      <para>And another clone, to simulate someone else making a
   1.287 +	change to the file. (This hints at the idea that it's not all
   1.288 +	that unusual to merge with yourself when you isolate tasks in
   1.289 +	separate repositories, and indeed to find and resolve
   1.290 +	conflicts while doing so.)</para>
   1.291 +
   1.292 +      <!-- &interaction.tour-merge-conflict.son; -->
   1.293 +
   1.294 +      <para>Having created two
   1.295 +	different versions of the file, we'll set up an environment
   1.296 +	suitable for running our merge.</para>
   1.297 +
   1.298 +      <!-- &interaction.tour-merge-conflict.pull; -->
   1.299 +
   1.300 +      <para>In this example, I won't use Mercurial's normal
   1.301 +	<command>hgmerge</command> program to do the merge, because it
   1.302 +	would drop my nice automated example-running tool into a
   1.303 +	graphical user interface.  Instead, I'll set
   1.304 +	<envar>HGMERGE</envar> to tell Mercurial to use the
   1.305 +	non-interactive <command>merge</command> command.  This is
   1.306 +	bundled with many Unix-like systems. If you're following this
   1.307 +	example on your computer, don't bother setting
   1.308 +	<envar>HGMERGE</envar>.</para>
   1.309 +
   1.310 +      <para><emphasis role="bold">XXX FIX THIS
   1.311 +	  EXAMPLE.</emphasis></para>
   1.312 +
   1.313 +      <!-- &interaction.tour-merge-conflict.merge; -->
   1.314 +
   1.315 +      <para>Because <command>merge</command> can't resolve the
   1.316 +	conflicting changes, it leaves <emphasis>merge
   1.317 +	  markers</emphasis> inside the file that has conflicts,
   1.318 +	indicating which lines have conflicts, and whether they came
   1.319 +	from our version of the file or theirs.</para>
   1.320 +
   1.321 +      <para>Mercurial can tell from the way <command>merge</command>
   1.322 +	exits that it wasn't able to merge successfully, so it tells
   1.323 +	us what commands we'll need to run if we want to redo the
   1.324 +	merging operation.  This could be useful if, for example, we
   1.325 +	were running a graphical merge tool and quit because we were
   1.326 +	confused or realised we had made a mistake.</para>
   1.327 +
   1.328 +      <para>If automatic or manual merges fail, there's nothing to
   1.329 +	prevent us from <quote>fixing up</quote> the affected files
   1.330 +	ourselves, and committing the results of our merge:</para>
   1.331 +
   1.332 +      <!-- &interaction.tour-merge-conflict.commit; -->
   1.333 +
   1.334 +    </sect2>
   1.335 +  </sect1>
   1.336 +  <sect1 id="sec:tour-merge:fetch">
   1.337 +    <title>Simplifying the pull-merge-commit sequence</title>
   1.338 +
   1.339 +    <para>The process of merging changes as outlined above is
   1.340 +      straightforward, but requires running three commands in
   1.341 +      sequence.</para>
   1.342 +    <programlisting>
   1.343 +      hg pull hg merge hg commit -m 'Merged remote changes'
   1.344 +    </programlisting>
   1.345 +    <para>In the case of the final commit, you also need to enter a
   1.346 +      commit message, which is almost always going to be a piece of
   1.347 +      uninteresting <quote>boilerplate</quote> text.</para>
   1.348 +
   1.349 +    <para>It would be nice to reduce the number of steps needed, if
   1.350 +      this were possible.  Indeed, Mercurial is distributed with an
   1.351 +      extension called <literal role="hg-ext">fetch</literal> that
   1.352 +      does just this.</para>
   1.353 +
   1.354 +    <para>Mercurial provides a flexible extension mechanism that lets
   1.355 +      people extend its functionality, while keeping the core of
   1.356 +      Mercurial small and easy to deal with.  Some extensions add new
   1.357 +      commands that you can use from the command line, while others
   1.358 +      work <quote>behind the scenes,</quote> for example adding
   1.359 +      capabilities to the server.</para>
   1.360 +
   1.361 +    <para>The <literal role="hg-ext">fetch</literal> extension adds a
   1.362 +      new command called, not surprisingly, <command role="hg-cmd">hg
   1.363 +	fetch</command>.  This extension acts as a combination of
   1.364 +      <command role="hg-cmd">hg pull</command>, <command
   1.365 +	role="hg-cmd">hg update</command> and <command
   1.366 +	role="hg-cmd">hg merge</command>.  It begins by pulling
   1.367 +      changes from another repository into the current repository.  If
   1.368 +      it finds that the changes added a new head to the repository, it
   1.369 +      begins a merge, then commits the result of the merge with an
   1.370 +      automatically-generated commit message.  If no new heads were
   1.371 +      added, it updates the working directory to the new tip
   1.372 +      changeset.</para>
   1.373 +
   1.374 +    <para>Enabling the <literal role="hg-ext">fetch</literal>
   1.375 +      extension is easy.  Edit your <filename
   1.376 +	role="special">.hgrc</filename>, and either go to the <literal
   1.377 +	role="rc-extensions">extensions</literal> section or create an
   1.378 +      <literal role="rc-extensions">extensions</literal> section. Then
   1.379 +      add a line that simply reads <quote><literal>fetch
   1.380 +	</literal></quote>.</para>
   1.381 +    <programlisting>
   1.382 +      [extensions] fetch =
   1.383 +    </programlisting>
   1.384 +    <para>(Normally, on the right-hand side of the
   1.385 +      <quote><literal>=</literal></quote> would appear the location of
   1.386 +      the extension, but since the <literal
   1.387 +	role="hg-ext">fetch</literal> extension is in the standard
   1.388 +      distribution, Mercurial knows where to search for it.)</para>
   1.389 +
   1.390 +  </sect1>
   1.391 +</chapter>
   1.392 +
   1.393 +<!--
   1.394 +local variables: 
   1.395 +sgml-parent-document: ("00book.xml" "book" "chapter")
   1.396 +end:
   1.397 +-->