hgbook

changeset 680:7226e5e750a6

Clean up chapter 8, and add content
author Bryan O'Sullivan <bos@serpentine.com>
date Tue Apr 21 23:49:27 2009 -0700 (2009-04-21)
parents 06458701453c
children 557552d4699f
files en/ch08-undo.xml en/examples/backout en/examples/bisect en/figs/bad-merge-1.dot en/figs/bad-merge-2.dot en/figs/bad-merge-3.dot en/figs/bad-merge-4.dot en/figs/bad-merge-5.dot
line diff
     1.1 --- a/en/ch08-undo.xml	Tue Apr 21 21:07:20 2009 -0700
     1.2 +++ b/en/ch08-undo.xml	Tue Apr 21 23:49:27 2009 -0700
     1.3 @@ -127,17 +127,17 @@
     1.4  	repository&emdash;particularly if it's a shared
     1.5  	repository&emdash;it has essentially <quote>escaped into the
     1.6  	  wild,</quote> and you'll have to recover from your mistake
     1.7 -	in a different way.  What will happen if you push a changeset
     1.8 -	somewhere, then roll it back, then pull from the repository
     1.9 -	you pushed to, is that the changeset will reappear in your
    1.10 -	repository.</para>
    1.11 -
    1.12 -      <para id="x_df">(If you absolutely know for sure that the change you want
    1.13 -	to roll back is the most recent change in the repository that
    1.14 -	you pushed to, <emphasis>and</emphasis> you know that nobody
    1.15 -	else could have pulled it from that repository, you can roll
    1.16 -	back the changeset there, too, but you really should really
    1.17 -	not rely on this working reliably.  If you do this, sooner or
    1.18 +	in a different way.  If you push a changeset somewhere, then
    1.19 +	roll it back, then pull from the repository you pushed to, the
    1.20 +	changeset you thought you'd gotten rid of will simply reappear
    1.21 +	in your repository.</para>
    1.22 +
    1.23 +      <para id="x_df">(If you absolutely know for sure that the change
    1.24 +	you want to roll back is the most recent change in the
    1.25 +	repository that you pushed to, <emphasis>and</emphasis> you
    1.26 +	know that nobody else could have pulled it from that
    1.27 +	repository, you can roll back the changeset there, too, but
    1.28 +	you really should not expect this to work reliably.  Sooner or
    1.29  	later a change really will make it into a repository that you
    1.30  	don't directly control (or have forgotten about), and come
    1.31  	back to bite you.)</para>
    1.32 @@ -193,6 +193,21 @@
    1.33  
    1.34      &interaction.daily.revert.status;
    1.35  
    1.36 +    <tip>
    1.37 +      <title>Be careful with <filename>.orig</filename> files</title>
    1.38 +
    1.39 +      <para>It's extremely unlikely that you are either using
    1.40 +	Mercurial to manage files with <filename>.orig</filename>
    1.41 +	extensions or that you even care about the contents of such
    1.42 +	files.  Just in case, though, it's useful to remember that
    1.43 +	<command role="hg-cmd">hg revert</command> will
    1.44 +	unconditionally overwrite an existing file with a
    1.45 +	<filename>.orig</filename> extension. For instance, if you
    1.46 +	already have a file named <filename>foo.orig</filename> when
    1.47 +	you revert <filename>foo</filename>, the contents of
    1.48 +	<filename>foo.orig</filename> will be clobbered.</para>
    1.49 +    </tip>
    1.50 +
    1.51      <para id="x_e6">Here is a summary of the cases that the <command
    1.52  	role="hg-cmd">hg revert</command> command can deal with.  We
    1.53        will describe each of these in more detail in the section that
    1.54 @@ -249,63 +264,27 @@
    1.55  	with the copied-from file.</para>
    1.56  
    1.57        &interaction.daily.revert.copy;
    1.58 -
    1.59 -      <sect3>
    1.60 -	<title>A slightly special case: reverting a rename</title>
    1.61 -
    1.62 -	<para id="x_ef">If you <command role="hg-cmd">hg rename</command> a
    1.63 -	  file, there is one small detail that you should remember.
    1.64 -	  When you <command role="hg-cmd">hg revert</command> a
    1.65 -	  rename, it's not enough to provide the name of the
    1.66 -	  renamed-to file, as you can see here.</para>
    1.67 -
    1.68 -	&interaction.daily.revert.rename;
    1.69 -
    1.70 -	<para id="x_f0">As you can see from the output of <command
    1.71 -	    role="hg-cmd">hg status</command>, the renamed-to file is
    1.72 -	  no longer identified as added, but the
    1.73 -	  renamed-<emphasis>from</emphasis> file is still removed!
    1.74 -	  This is counter-intuitive (at least to me), but at least
    1.75 -	  it's easy to deal with.</para>
    1.76 -
    1.77 -	&interaction.daily.revert.rename-orig;
    1.78 -
    1.79 -	<para id="x_f1">So remember, to revert a <command role="hg-cmd">hg
    1.80 -	    rename</command>, you must provide
    1.81 -	  <emphasis>both</emphasis> the source and destination
    1.82 -	  names.</para>
    1.83 -
    1.84 -	<para id="x_f2">% TODO: the output doesn't look like it will be
    1.85 -	  removed!</para>
    1.86 -
    1.87 -	<para id="x_f3">(By the way, if you rename a file, then modify the
    1.88 -	  renamed-to file, then revert both components of the rename,
    1.89 -	  when Mercurial restores the file that was removed as part of
    1.90 -	  the rename, it will be unmodified. If you need the
    1.91 -	  modifications in the renamed-to file to show up in the
    1.92 -	  renamed-from file, don't forget to copy them over.)</para>
    1.93 -
    1.94 -	<para id="x_f4">These fiddly aspects of reverting a rename arguably
    1.95 -	  constitute a small bug in Mercurial.</para>
    1.96 -
    1.97 -      </sect3>
    1.98      </sect2>
    1.99    </sect1>
   1.100 +
   1.101    <sect1>
   1.102      <title>Dealing with committed changes</title>
   1.103  
   1.104 -    <para id="x_f5">Consider a case where you have committed a change $a$, and
   1.105 -      another change $b$ on top of it; you then realise that change
   1.106 -      $a$ was incorrect.  Mercurial lets you <quote>back out</quote>
   1.107 -      an entire changeset automatically, and building blocks that let
   1.108 -      you reverse part of a changeset by hand.</para>
   1.109 +    <para id="x_f5">Consider a case where you have committed a change
   1.110 +      <emphasis>a</emphasis>, and another change
   1.111 +      <emphasis>b</emphasis> on top of it; you then realise that
   1.112 +      change <emphasis>a</emphasis> was incorrect.  Mercurial lets you
   1.113 +      <quote>back out</quote> an entire changeset automatically, and
   1.114 +      building blocks that let you reverse part of a changeset by
   1.115 +      hand.</para>
   1.116  
   1.117      <para id="x_f6">Before you read this section, here's something to
   1.118        keep in mind: the <command role="hg-cmd">hg backout</command>
   1.119 -      command undoes changes by <emphasis>adding</emphasis> history,
   1.120 -      not by modifying or erasing it.  It's the right tool to use if
   1.121 -      you're fixing bugs, but not if you're trying to undo some change
   1.122 -      that has catastrophic consequences.  To deal with those, see
   1.123 +      command undoes the effect of a change by
   1.124 +      <emphasis>adding</emphasis> to your repository's history, not by
   1.125 +      modifying or erasing it.  It's the right tool to use if you're
   1.126 +      fixing bugs, but not if you're trying to undo some change that
   1.127 +      has catastrophic consequences.  To deal with those, see
   1.128        <xref linkend="sec:undo:aaaiiieee"/>.</para>
   1.129  
   1.130      <sect2>
   1.131 @@ -392,17 +371,17 @@
   1.132  
   1.133        <para id="x_100">As the graphical history in <xref
   1.134  	  linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial
   1.135 -	actually commits <emphasis>two</emphasis> changes in this kind
   1.136 -	of situation (the box-shaped nodes are the ones that Mercurial
   1.137 -	commits automatically).  Before Mercurial begins the backout
   1.138 -	process, it first remembers what the current parent of the
   1.139 -	working directory is.  It then backs out the target changeset,
   1.140 -	and commits that as a changeset.  Finally, it merges back to
   1.141 -	the previous parent of the working directory, and commits the
   1.142 -	result of the merge.</para>
   1.143 -
   1.144 -      <para id="x_101">% TODO: to me it looks like mercurial doesn't commit the
   1.145 -	second merge automatically!</para>
   1.146 +	still commits one change in this kind of situation (the
   1.147 +	box-shaped node is the ones that Mercurial commits
   1.148 +	automatically), but the revision graph now looks different.
   1.149 +	Before Mercurial begins the backout process, it first
   1.150 +	remembers what the current parent of the working directory is.
   1.151 +	It then backs out the target changeset, and commits that as a
   1.152 +	changeset.  Finally, it merges back to the previous parent of
   1.153 +	the working directory, but notice that it <emphasis>does not
   1.154 +	  commit</emphasis> the result of the merge.  The repository
   1.155 +	now contains two heads, and the working directory is in a
   1.156 +	merge state.</para>
   1.157  
   1.158        <figure id="fig:undo:backout-non-tip">
   1.159  	<title>Automated backout of a non-tip change using the
   1.160 @@ -417,6 +396,14 @@
   1.161  	  were</quote>, only with some extra history that undoes the
   1.162  	effect of the changeset you wanted to back out.</para>
   1.163  
   1.164 +      <para>You might wonder why Mercurial does not commit the result
   1.165 +	of the merge that it performed.  The reason lies in Mercurial
   1.166 +	behaving conservatively: a merge naturally has more scope for
   1.167 +	error than simply undoing the effect of the tip changeset,
   1.168 +	so your work will be safest if you first inspect (and test!)
   1.169 +	the result of the merge, <emphasis>then</emphasis> commit
   1.170 +	it.</para>
   1.171 +
   1.172        <sect3>
   1.173  	<title>Always use the <option
   1.174  	    role="hg-opt-backout">--merge</option> option</title>
   1.175 @@ -530,12 +517,12 @@
   1.176  	</listitem>
   1.177  	<listitem><para id="x_112">It remembers the current parent of the working
   1.178  	    directory.  Let's call this changeset
   1.179 -	    <literal>orig</literal></para>
   1.180 +	    <literal>orig</literal>.</para>
   1.181  	</listitem>
   1.182  	<listitem><para id="x_113">It does the equivalent of a <command
   1.183  	      role="hg-cmd">hg update</command> to sync the working
   1.184  	    directory to the changeset you want to back out.  Let's
   1.185 -	    call this changeset <literal>backout</literal></para>
   1.186 +	    call this changeset <literal>backout</literal>.</para>
   1.187  	</listitem>
   1.188  	<listitem><para id="x_114">It finds the parent of that changeset.  Let's
   1.189  	    call that changeset <literal>parent</literal>.</para>
   1.190 @@ -632,7 +619,7 @@
   1.191  
   1.192      <para id="x_120">If a situation like this arises, and you know which
   1.193        repositories your bad change has propagated into, you can
   1.194 -      <emphasis>try</emphasis> to get rid of the changeefrom
   1.195 +      <emphasis>try</emphasis> to get rid of the change from
   1.196        <emphasis>every</emphasis> one of those repositories.  This is,
   1.197        of course, not a satisfactory solution: if you miss even a
   1.198        single repository while you're expunging, the change is still
   1.199 @@ -644,10 +631,105 @@
   1.200        provide a way to <quote>punch a hole</quote> in history, leaving
   1.201        changesets intact.</para>
   1.202  
   1.203 -    <para id="x_122">XXX This needs filling out.  The
   1.204 -      <literal>hg-replay</literal> script in the
   1.205 -      <literal>examples</literal> directory works, but doesn't handle
   1.206 -      merge changesets.  Kind of an important omission.</para>
   1.207 +    <sect2>
   1.208 +      <title>Backing out a merge</title>
   1.209 +
   1.210 +      <para>Since merges are often complicated, it is not unheard of
   1.211 +	for a merge to be mangled badly, but committed erroneously.
   1.212 +	Mercurial provides an important safeguard against bad merges
   1.213 +	by refusing to commit unresolved files, but human ingenuity
   1.214 +	guarantees that it is still possible to mess a merge up and
   1.215 +	commit it.</para>
   1.216 +
   1.217 +      <para>Given a bad merge that has been committed, usually the
   1.218 +	best way to approach it is to simply try to repair the damage
   1.219 +	by hand.  A complete disaster that cannot be easily fixed up
   1.220 +	by hand ought to be very rare, but the <command
   1.221 +	  role="hg-cmd">hg backout</command> command may help in
   1.222 +	making the cleanup easier. It offers a <option
   1.223 +	  role="hg-opt-backout">--parent</option> option, which lets
   1.224 +	you specify which parent to revert to when backing out a
   1.225 +	merge.</para>
   1.226 +
   1.227 +      <figure id="fig:undo:bad-merge-1">
   1.228 +	<title>A bad merge</title>
   1.229 +	<mediaobject>
   1.230 +	  <imageobject><imagedata fileref="figs/bad-merge-1.png"/></imageobject>
   1.231 +	  <textobject><phrase>XXX add text</phrase></textobject>
   1.232 +	</mediaobject>
   1.233 +      </figure>
   1.234 +
   1.235 +      <para>Suppose we have a revision graph like that in <xref
   1.236 +	  linkend="fig:undo:bad-merge-1"/>.  What we'd like is to
   1.237 +	<emphasis>redo</emphasis> the merge of revisions 2 and
   1.238 +	3.</para>
   1.239 +
   1.240 +      <para>One way to do so would be as follows.</para>
   1.241 +
   1.242 +      <orderedlist>
   1.243 +	<listitem>
   1.244 +	  <para>Call <command role="hg-cmd">hg backout --rev=4
   1.245 +	      --parent=2</command>.  This tells <command
   1.246 +	      role="hg-cmd">hg backout</command> to back out revision
   1.247 +	    4, which is the bad merge, and to when deciding which
   1.248 +	    revision to prefer, to choose parent 2, one of the parents
   1.249 +	    of the merge.  The effect can be seen in <xref
   1.250 +	      linkend="fig:undo:bad-merge-2"/>.</para>
   1.251 +	  <figure id="fig:undo:bad-merge-2">
   1.252 +	    <title>Backing out the merge, favoring one parent</title>
   1.253 +	    <mediaobject>
   1.254 +	      <imageobject><imagedata fileref="figs/bad-merge-2.png"/></imageobject>
   1.255 +	      <textobject><phrase>XXX add text</phrase></textobject>
   1.256 +	    </mediaobject>
   1.257 +	  </figure>
   1.258 +	</listitem>
   1.259 +
   1.260 +	<listitem>
   1.261 +	  <para>Call <command role="hg-cmd">hg backout --rev=4
   1.262 +	      --parent=3</command>.  This tells <command
   1.263 +	      role="hg-cmd">hg backout</command> to back out revision
   1.264 +	    4 again, but this time to choose parent 3, the other
   1.265 +	    parent of the merge.  The result is visible in <xref
   1.266 +	    linkend="fig:undo:bad-merge-3"/>, in which the repository
   1.267 +	    now contains three heads.</para>
   1.268 +	  <figure id="fig:undo:bad-merge-3">
   1.269 +	    <title>Backing out the merge, favoring the other
   1.270 +	      parent</title>
   1.271 +	    <mediaobject>
   1.272 +	      <imageobject><imagedata fileref="figs/bad-merge-3.png"/></imageobject>
   1.273 +	      <textobject><phrase>XXX add text</phrase></textobject>
   1.274 +	    </mediaobject>
   1.275 +	  </figure>
   1.276 +	</listitem>
   1.277 +
   1.278 +	<listitem>
   1.279 +	  <para>Redo the bad merge by merging the two backout heads,
   1.280 +	    which reduces the number of heads in the repository to
   1.281 +	    two, as can be seen in <xref
   1.282 +	      linkend="fig:undo:bad-merge-4"/>.</para>
   1.283 +	  <figure id="fig:undo:bad-merge-4">
   1.284 +	    <title>Merging the backouts</title>
   1.285 +	    <mediaobject>
   1.286 +	      <imageobject><imagedata fileref="figs/bad-merge-4.png"/></imageobject>
   1.287 +	      <textobject><phrase>XXX add text</phrase></textobject>
   1.288 +	    </mediaobject>
   1.289 +	  </figure>
   1.290 +	</listitem>
   1.291 +
   1.292 +	<listitem>
   1.293 +	  <para>Merge with the commit that was made after the bad
   1.294 +	    merge, as shown in <xref
   1.295 +	      linkend="fig:undo:bad-merge-5"/>.</para>
   1.296 +	  <figure id="fig:undo:bad-merge-5">
   1.297 +	    <title>Merging the backouts</title>
   1.298 +	    <mediaobject>
   1.299 +	      <imageobject><imagedata fileref="figs/bad-merge-5.png"/></imageobject>
   1.300 +	      <textobject><phrase>XXX add text</phrase></textobject>
   1.301 +	    </mediaobject>
   1.302 +	  </figure>
   1.303 +	</listitem>
   1.304 +      </orderedlist>
   1.305 +    </sect2>
   1.306  
   1.307      <sect2>
   1.308        <title>Protect yourself from <quote>escaped</quote>
   1.309 @@ -670,12 +752,62 @@
   1.310  	propagate into the central repository.  Better yet, this
   1.311  	happens without any need for explicit intervention.</para>
   1.312  
   1.313 -      <para id="x_125">For instance, an incoming change hook that verifies that a
   1.314 -	changeset will actually compile can prevent people from
   1.315 -	inadvertantly <quote>breaking the build</quote>.</para>
   1.316 -
   1.317 +      <para id="x_125">For instance, an incoming change hook that
   1.318 +	verifies that a changeset will actually compile can prevent
   1.319 +	people from inadvertently <quote>breaking the
   1.320 +	  build</quote>.</para>
   1.321 +    </sect2>
   1.322 +
   1.323 +    <sect2>
   1.324 +      <title>What to do about sensitive changes that escape</title>
   1.325 +
   1.326 +      <para>Even a carefully run project can suffer an unfortunate
   1.327 +	event such as the committing and uncontrolled propagation of a
   1.328 +	file that contains important passwords.</para>
   1.329 +
   1.330 +      <para>If something like this happens to you, and the information
   1.331 +	that gets accidentally propagated is truly sensitive, your
   1.332 +	first step should be to mitigate the effect of the leak
   1.333 +	without trying to control the leak itself. If you are not 100%
   1.334 +	certain that you know exactly who could have seen the changes,
   1.335 +	you should immediately change passwords, cancel credit cards,
   1.336 +	or find some other way to make sure that the information that
   1.337 +	has leaked is no longer useful.  In other words, assume that
   1.338 +	the change has propagated far and wide, and that there's
   1.339 +	nothing more you can do.</para>
   1.340 +
   1.341 +      <para>You might hope that there would be mechanisms you could
   1.342 +	use to either figure out who has seen a change or to erase the
   1.343 +	change permanently everywhere, but there are good reasons why
   1.344 +	these are not possible.</para>
   1.345 +
   1.346 +      <para>Mercurial does not provide an audit trail of who has
   1.347 +	pulled changes from a repository, because it is usually either
   1.348 +	impossible to record such information or trivial to spoof it.
   1.349 +	In a multi-user or networked environment, you should thus be
   1.350 +	extremely skeptical of yourself if you think that you have
   1.351 +	identified every place that a sensitive changeset has
   1.352 +	propagated to.  Don't forget that people can and will send
   1.353 +	bundles by email, have their backup software save data
   1.354 +	offsite, carry repositories on USB sticks, and find other
   1.355 +	completely innocent ways to confound your attempts to track
   1.356 +	down every copy of a problematic change.</para>
   1.357 +
   1.358 +      <para>Mercurial also does not provide a way to make a file or
   1.359 +	changeset completely disappear from history, because there is
   1.360 +	no way to enforce its disappearance; someone could easily
   1.361 +	modify their copy of Mercurial to ignore such directives. In
   1.362 +	addition, even if Mercurial provided such a capability,
   1.363 +	someone who simply hadn't pulled a <quote>make this file
   1.364 +	  disappear</quote> changeset wouldn't be affected by it, nor
   1.365 +	would web crawlers visiting at the wrong time, disk backups,
   1.366 +	or other mechanisms.  Indeed, no distributed revision control
   1.367 +	system can make data reliably vanish. Providing the illusion
   1.368 +	of such control could easily give a false sense of security,
   1.369 +	and be worse than not providing it at all.</para>
   1.370      </sect2>
   1.371    </sect1>
   1.372 +
   1.373    <sect1 id="sec:undo:bisect">
   1.374      <title>Finding the source of a bug</title>
   1.375  
   1.376 @@ -815,11 +947,11 @@
   1.377  	  <itemizedlist>
   1.378  	    <listitem><para id="x_139">If the test succeeded, you tell <command
   1.379  		  role="hg-cmd">hg bisect</command> by running the
   1.380 -		<command role="hg-cmd">hg bisect good</command>
   1.381 +		<command role="hg-cmd">hg bisect --good</command>
   1.382  		command.</para>
   1.383  	    </listitem>
   1.384  	    <listitem><para id="x_13a">If it failed, run the <command
   1.385 -		  role="hg-cmd">hg bisect bad</command>
   1.386 +		  role="hg-cmd">hg bisect --bad</command>
   1.387  		command.</para></listitem></itemizedlist>
   1.388  	</listitem>
   1.389  	<listitem><para id="x_13b">The command uses your information to decide
   1.390 @@ -909,13 +1041,13 @@
   1.391  
   1.392        <para id="x_14a">When you're finished using the <command role="hg-cmd">hg
   1.393  	  bisect</command> command in a repository, you can use the
   1.394 -	<command role="hg-cmd">hg bisect reset</command> command to
   1.395 +	<command role="hg-cmd">hg bisect --reset</command> command to
   1.396  	drop the information it was using to drive your search.  The
   1.397  	command doesn't use much space, so it doesn't matter if you
   1.398  	forget to run this command.  However, <command
   1.399  	  role="hg-cmd">hg bisect</command> won't let you start a new
   1.400  	search in that repository until you do a <command
   1.401 -	  role="hg-cmd">hg bisect reset</command>.</para>
   1.402 +	  role="hg-cmd">hg bisect --reset</command>.</para>
   1.403  
   1.404        &interaction.bisect.search.reset;
   1.405  
     2.1 --- a/en/examples/backout	Tue Apr 21 21:07:20 2009 -0700
     2.2 +++ b/en/examples/backout	Tue Apr 21 23:49:27 2009 -0700
     2.3 @@ -68,6 +68,10 @@
     2.4  
     2.5  hg heads
     2.6  
     2.7 +#$ name:
     2.8 +
     2.9 +echo 'first change' > myfile
    2.10 +
    2.11  #$ name: manual.cat
    2.12  
    2.13  cat myfile
     3.1 --- a/en/examples/bisect	Tue Apr 21 21:07:20 2009 -0700
     3.2 +++ b/en/examples/bisect	Tue Apr 21 23:49:27 2009 -0700
     3.3 @@ -37,15 +37,15 @@
     3.4  
     3.5  #$ name: search.init
     3.6  
     3.7 -hg bisect init
     3.8 +hg bisect --reset
     3.9  
    3.10  #$ name: search.bad-init
    3.11  
    3.12 -hg bisect bad
    3.13 +hg bisect --bad
    3.14  
    3.15  #$ name: search.good-init
    3.16  
    3.17 -hg bisect good 10
    3.18 +hg bisect --good 10
    3.19  
    3.20  #$ name: search.step1
    3.21  
    3.22 @@ -70,7 +70,7 @@
    3.23    fi
    3.24  
    3.25    echo this revision is $result
    3.26 -  hg bisect $result
    3.27 +  hg bisect --$result
    3.28  }
    3.29    
    3.30  #$ name: search.step2
    3.31 @@ -85,7 +85,7 @@
    3.32  
    3.33  #$ name: search.reset
    3.34  
    3.35 -hg bisect reset
    3.36 +hg bisect --reset
    3.37  
    3.38  #$ name:
    3.39  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/en/figs/bad-merge-1.dot	Tue Apr 21 23:49:27 2009 -0700
     4.3 @@ -0,0 +1,13 @@
     4.4 +digraph bad_merge_1 {
     4.5 +	ancestor [label="1: ancestor"];
     4.6 +	left [label="2: my change"];
     4.7 +	right [label="3: your change"];
     4.8 +	bad [label="4: bad merge"];
     4.9 +	new [label="5: new change"];
    4.10 +
    4.11 +	ancestor -> left;
    4.12 +	ancestor -> right;
    4.13 +	left -> bad;
    4.14 +	right -> bad;
    4.15 +	bad -> new;
    4.16 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/en/figs/bad-merge-2.dot	Tue Apr 21 23:49:27 2009 -0700
     5.3 @@ -0,0 +1,18 @@
     5.4 +digraph bad_merge_2 {
     5.5 +	ancestor [label="1: ancestor",color=grey,fontcolor=grey];
     5.6 +	left [label="2: my change",color=grey,fontcolor=grey];
     5.7 +	right [label="3: your change",color=grey,fontcolor=grey];
     5.8 +	bad [label="4: bad merge",color=grey,fontcolor=grey];
     5.9 +	new [label="5: new change",color=grey,fontcolor=grey];
    5.10 +
    5.11 +	bak_left [label="6: backout 1 of\nbad merge",shape=box];
    5.12 +
    5.13 +	ancestor -> left [color=grey];
    5.14 +	ancestor -> right [color=grey];
    5.15 +	left -> bad [color=grey];
    5.16 +	right -> bad [color=grey];
    5.17 +	bad -> new [color=grey];
    5.18 +
    5.19 +	bad -> bak_left;
    5.20 +	left -> bak_left [style=dotted,label="--parent=2"];
    5.21 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/en/figs/bad-merge-3.dot	Tue Apr 21 23:49:27 2009 -0700
     6.3 @@ -0,0 +1,22 @@
     6.4 +digraph bad_merge_3 {
     6.5 +	ancestor [label="1: ancestor",color="#bbbbbb",fontcolor="#bbbbbb"];
     6.6 +	left [label="2: my change",color="#bbbbbb",fontcolor="#bbbbbb"];
     6.7 +	right [label="3: your change",color="#bbbbbb",fontcolor="#bbbbbb"];
     6.8 +	bad [label="4: bad merge",color="#bbbbbb",fontcolor="#bbbbbb"];
     6.9 +	new [label="5: new change",color="#bbbbbb",fontcolor="#bbbbbb"];
    6.10 +
    6.11 +	bak_left [label="6: backout 1 of\nbad merge",color=grey,shape=box];
    6.12 +	bak_right [label="8: backout 2 of\nbad merge",shape=box];
    6.13 +
    6.14 +	ancestor -> left [color="#bbbbbb"];
    6.15 +	ancestor -> right [color="#bbbbbb"];
    6.16 +	left -> bad [color="#bbbbbb"];
    6.17 +	right -> bad [color="#bbbbbb"];
    6.18 +	bad -> new [color="#bbbbbb"];
    6.19 +
    6.20 +	bad -> bak_left [color=grey];
    6.21 +	left -> bak_left [style=dotted,label="--parent=2",color=grey,fontcolor=grey];
    6.22 +
    6.23 +	bad -> bak_right;
    6.24 +	right -> bak_right [style=dotted,label="--parent=3"];
    6.25 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/en/figs/bad-merge-4.dot	Tue Apr 21 23:49:27 2009 -0700
     7.3 @@ -0,0 +1,26 @@
     7.4 +digraph bad_merge_4 {
     7.5 +	ancestor [label="1: ancestor",color="#bbbbbb",fontcolor="#bbbbbb"];
     7.6 +	left [label="2: my change",color="#bbbbbb",fontcolor="#bbbbbb"];
     7.7 +	right [label="3: your change",color="#bbbbbb",fontcolor="#bbbbbb"];
     7.8 +	bad [label="4: bad merge",color="#bbbbbb",fontcolor="#bbbbbb"];
     7.9 +	new [label="5: new change",color="#bbbbbb",fontcolor="#bbbbbb"];
    7.10 +
    7.11 +	bak_left [label="6: backout 1 of\nbad merge",color=grey,fontcolor=grey,shape=box];
    7.12 +	bak_right [label="7: backout 2 of\nbad merge",color=grey,fontcolor=grey,shape=box];
    7.13 +	good [label="8: merge\nof backouts",shape=box];
    7.14 +
    7.15 +	ancestor -> left [color="#bbbbbb"];
    7.16 +	ancestor -> right [color="#bbbbbb"];
    7.17 +	left -> bad [color="#bbbbbb"];
    7.18 +	right -> bad [color="#bbbbbb"];
    7.19 +	bad -> new [color="#bbbbbb"];
    7.20 +
    7.21 +	bad -> bak_left [color=grey];
    7.22 +	left -> bak_left [style=dotted,label="--parent=2",color=grey,fontcolor=grey];
    7.23 +
    7.24 +	bad -> bak_right [color=grey];
    7.25 +	right -> bak_right [style=dotted,label="--parent=3",color=grey,fontcolor=grey];
    7.26 +
    7.27 +	bak_left -> good;
    7.28 +	bak_right -> good;
    7.29 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/en/figs/bad-merge-5.dot	Tue Apr 21 23:49:27 2009 -0700
     8.3 @@ -0,0 +1,30 @@
     8.4 +digraph bad_merge_5 {
     8.5 +	ancestor [label="1: ancestor",color="#bbbbbb",fontcolor="#bbbbbb"];
     8.6 +	left [label="2: my change",color="#bbbbbb",fontcolor="#bbbbbb"];
     8.7 +	right [label="3: your change",color="#bbbbbb",fontcolor="#bbbbbb"];
     8.8 +	bad [label="4: bad merge",color="#bbbbbb",fontcolor="#bbbbbb"];
     8.9 +	new [label="5: new change",color=grey,fontcolor=grey];
    8.10 +
    8.11 +	bak_left [label="6: backout 1 of\nbad merge",color="#bbbbbb",fontcolor="#bbbbbb",shape=box];
    8.12 +	bak_right [label="7: backout 2 of\nbad merge",color="#bbbbbb",fontcolor="#bbbbbb",shape=box];
    8.13 +	good [label="8: merge\nof backouts",color=grey,fontcolor=grey,shape=box];
    8.14 +	last [label="9: merge with\nnew change",shape=box];
    8.15 +
    8.16 +	ancestor -> left [color="#bbbbbb"];
    8.17 +	ancestor -> right [color="#bbbbbb"];
    8.18 +	left -> bad [color="#bbbbbb"];
    8.19 +	right -> bad [color="#bbbbbb"];
    8.20 +	bad -> new [color="#bbbbbb"];
    8.21 +
    8.22 +	bad -> bak_left [color="#bbbbbb"];
    8.23 +	left -> bak_left [style=dotted,label="--parent=2",color="#bbbbbb",fontcolor="#bbbbbb"];
    8.24 +
    8.25 +	bad -> bak_right [color="#bbbbbb"];
    8.26 +	right -> bak_right [style=dotted,label="--parent=3",color="#bbbbbb",fontcolor="#bbbbbb"];
    8.27 +
    8.28 +	bak_left -> good [color=grey];
    8.29 +	bak_right -> good [color=grey];
    8.30 +
    8.31 +	good -> last;
    8.32 +	new -> last;
    8.33 +}