hgbook

diff en/ch09-undo.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
children 8fcd44708f41
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/en/ch09-undo.xml	Wed Feb 18 00:22:09 2009 -0800
     1.3 @@ -0,0 +1,997 @@
     1.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
     1.5 +
     1.6 +<chapter id="chap:undo">
     1.7 +  <title>Finding and fixing your mistakes</title>
     1.8 +
     1.9 +  <para>To err might be human, but to really handle the consequences
    1.10 +    well takes a top-notch revision control system.  In this chapter,
    1.11 +    we'll discuss some of the techniques you can use when you find
    1.12 +    that a problem has crept into your project.  Mercurial has some
    1.13 +    highly capable features that will help you to isolate the sources
    1.14 +    of problems, and to handle them appropriately.</para>
    1.15 +
    1.16 +  <sect1>
    1.17 +    <title>Erasing local history</title>
    1.18 +
    1.19 +    <sect2>
    1.20 +      <title>The accidental commit</title>
    1.21 +
    1.22 +      <para>I have the occasional but persistent problem of typing
    1.23 +	rather more quickly than I can think, which sometimes results
    1.24 +	in me committing a changeset that is either incomplete or
    1.25 +	plain wrong.  In my case, the usual kind of incomplete
    1.26 +	changeset is one in which I've created a new source file, but
    1.27 +	forgotten to <command role="hg-cmd">hg add</command> it.  A
    1.28 +	<quote>plain wrong</quote> changeset is not as common, but no
    1.29 +	less annoying.</para>
    1.30 +
    1.31 +    </sect2>
    1.32 +    <sect2 id="sec:undo:rollback">
    1.33 +      <title>Rolling back a transaction</title>
    1.34 +
    1.35 +      <para>In section <xref linkend="sec:concepts:txn"/>, I mentioned
    1.36 +	that Mercurial treats each modification of a repository as a
    1.37 +	<emphasis>transaction</emphasis>.  Every time you commit a
    1.38 +	changeset or pull changes from another repository, Mercurial
    1.39 +	remembers what you did.  You can undo, or <emphasis>roll
    1.40 +	  back</emphasis>, exactly one of these actions using the
    1.41 +	<command role="hg-cmd">hg rollback</command> command.  (See
    1.42 +	section <xref linkend="sec:undo:rollback-after-push"/> for an
    1.43 +	important caveat about the use of this command.)</para>
    1.44 +
    1.45 +      <para>Here's a mistake that I often find myself making:
    1.46 +	committing a change in which I've created a new file, but
    1.47 +	forgotten to <command role="hg-cmd">hg add</command> it. <!--
    1.48 +	&interaction.rollback.commit; --> Looking at the output of
    1.49 +	<command role="hg-cmd">hg status</command> after the commit
    1.50 +	immediately confirms the error. <!--
    1.51 +	&interaction.rollback.status; --> The commit captured the
    1.52 +	changes to the file <filename>a</filename>, but not the new
    1.53 +	file <filename>b</filename>.  If I were to push this changeset
    1.54 +	to a repository that I shared with a colleague, the chances
    1.55 +	are high that something in <filename>a</filename> would refer
    1.56 +	to <filename>b</filename>, which would not be present in their
    1.57 +	repository when they pulled my changes.  I would thus become
    1.58 +	the object of some indignation.</para>
    1.59 +
    1.60 +      <para>However, luck is with me&emdash;I've caught my error
    1.61 +	before I pushed the changeset.  I use the <command
    1.62 +	  role="hg-cmd">hg rollback</command> command, and Mercurial
    1.63 +	makes that last changeset vanish. <!--
    1.64 +	&interaction.rollback.rollback; --> Notice that the changeset
    1.65 +	is no longer present in the repository's history, and the
    1.66 +	working directory once again thinks that the file
    1.67 +	<filename>a</filename> is modified.  The commit and rollback
    1.68 +	have left the working directory exactly as it was prior to the
    1.69 +	commit; the changeset has been completely erased.  I can now
    1.70 +	safely <command role="hg-cmd">hg add</command> the file
    1.71 +	<filename>b</filename>, and rerun my commit. <!--
    1.72 +	&interaction.rollback.add; --></para>
    1.73 +
    1.74 +    </sect2>
    1.75 +    <sect2>
    1.76 +      <title>The erroneous pull</title>
    1.77 +
    1.78 +      <para>It's common practice with Mercurial to maintain separate
    1.79 +	development branches of a project in different repositories.
    1.80 +	Your development team might have one shared repository for
    1.81 +	your project's <quote>0.9</quote> release, and another,
    1.82 +	containing different changes, for the <quote>1.0</quote>
    1.83 +	release.</para>
    1.84 +
    1.85 +      <para>Given this, you can imagine that the consequences could be
    1.86 +	messy if you had a local <quote>0.9</quote> repository, and
    1.87 +	accidentally pulled changes from the shared <quote>1.0</quote>
    1.88 +	repository into it.  At worst, you could be paying
    1.89 +	insufficient attention, and push those changes into the shared
    1.90 +	<quote>0.9</quote> tree, confusing your entire team (but don't
    1.91 +	worry, we'll return to this horror scenario later).  However,
    1.92 +	it's more likely that you'll notice immediately, because
    1.93 +	Mercurial will display the URL it's pulling from, or you will
    1.94 +	see it pull a suspiciously large number of changes into the
    1.95 +	repository.</para>
    1.96 +
    1.97 +      <para>The <command role="hg-cmd">hg rollback</command> command
    1.98 +	will work nicely to expunge all of the changesets that you
    1.99 +	just pulled.  Mercurial groups all changes from one <command
   1.100 +	  role="hg-cmd">hg pull</command> into a single transaction,
   1.101 +	so one <command role="hg-cmd">hg rollback</command> is all you
   1.102 +	need to undo this mistake.</para>
   1.103 +
   1.104 +    </sect2>
   1.105 +    <sect2 id="sec:undo:rollback-after-push">
   1.106 +      <title>Rolling back is useless once you've pushed</title>
   1.107 +
   1.108 +      <para>The value of the <command role="hg-cmd">hg
   1.109 +	  rollback</command> command drops to zero once you've pushed
   1.110 +	your changes to another repository.  Rolling back a change
   1.111 +	makes it disappear entirely, but <emphasis>only</emphasis> in
   1.112 +	the repository in which you perform the <command
   1.113 +	  role="hg-cmd">hg rollback</command>.  Because a rollback
   1.114 +	eliminates history, there's no way for the disappearance of a
   1.115 +	change to propagate between repositories.</para>
   1.116 +
   1.117 +      <para>If you've pushed a change to another
   1.118 +	repository&emdash;particularly if it's a shared
   1.119 +	repository&emdash;it has essentially <quote>escaped into the
   1.120 +	  wild,</quote> and you'll have to recover from your mistake
   1.121 +	in a different way.  What will happen if you push a changeset
   1.122 +	somewhere, then roll it back, then pull from the repository
   1.123 +	you pushed to, is that the changeset will reappear in your
   1.124 +	repository.</para>
   1.125 +
   1.126 +      <para>(If you absolutely know for sure that the change you want
   1.127 +	to roll back is the most recent change in the repository that
   1.128 +	you pushed to, <emphasis>and</emphasis> you know that nobody
   1.129 +	else could have pulled it from that repository, you can roll
   1.130 +	back the changeset there, too, but you really should really
   1.131 +	not rely on this working reliably.  If you do this, sooner or
   1.132 +	later a change really will make it into a repository that you
   1.133 +	don't directly control (or have forgotten about), and come
   1.134 +	back to bite you.)</para>
   1.135 +
   1.136 +    </sect2>
   1.137 +    <sect2>
   1.138 +      <title>You can only roll back once</title>
   1.139 +
   1.140 +      <para>Mercurial stores exactly one transaction in its
   1.141 +	transaction log; that transaction is the most recent one that
   1.142 +	occurred in the repository. This means that you can only roll
   1.143 +	back one transaction.  If you expect to be able to roll back
   1.144 +	one transaction, then its predecessor, this is not the
   1.145 +	behaviour you will get. <!-- &interaction.rollback.twice; -->
   1.146 +	Once you've rolled back one transaction in a repository, you
   1.147 +	can't roll back again in that repository until you perform
   1.148 +	another commit or pull.</para>
   1.149 +
   1.150 +    </sect2>
   1.151 +  </sect1>
   1.152 +  <sect1>
   1.153 +    <title>Reverting the mistaken change</title>
   1.154 +
   1.155 +    <para>If you make a modification to a file, and decide that you
   1.156 +      really didn't want to change the file at all, and you haven't
   1.157 +      yet committed your changes, the <command role="hg-cmd">hg
   1.158 +	revert</command> command is the one you'll need.  It looks at
   1.159 +      the changeset that's the parent of the working directory, and
   1.160 +      restores the contents of the file to their state as of that
   1.161 +      changeset. (That's a long-winded way of saying that, in the
   1.162 +      normal case, it undoes your modifications.)</para>
   1.163 +
   1.164 +    <para>Let's illustrate how the <command role="hg-cmd">hg
   1.165 +	revert</command> command works with yet another small example.
   1.166 +      We'll begin by modifying a file that Mercurial is already
   1.167 +      tracking. <!-- &interaction.daily.revert.modify; --> If we don't
   1.168 +      want that change, we can simply <command role="hg-cmd">hg
   1.169 +	revert</command> the file. <!--
   1.170 +      &interaction.daily.revert.unmodify; --> The <command
   1.171 +	role="hg-cmd">hg revert</command> command provides us with an
   1.172 +      extra degree of safety by saving our modified file with a
   1.173 +      <filename>.orig</filename> extension. <!--
   1.174 +      &interaction.daily.revert.status; --></para>
   1.175 +
   1.176 +    <para>Here is a summary of the cases that the <command
   1.177 +	role="hg-cmd">hg revert</command> command can deal with.  We
   1.178 +      will describe each of these in more detail in the section that
   1.179 +      follows.</para>
   1.180 +    <itemizedlist>
   1.181 +      <listitem><para>If you modify a file, it will restore the file
   1.182 +	  to its unmodified state.</para>
   1.183 +      </listitem>
   1.184 +      <listitem><para>If you <command role="hg-cmd">hg add</command> a
   1.185 +	  file, it will undo the <quote>added</quote> state of the
   1.186 +	  file, but leave the file itself untouched.</para>
   1.187 +      </listitem>
   1.188 +      <listitem><para>If you delete a file without telling Mercurial,
   1.189 +	  it will restore the file to its unmodified contents.</para>
   1.190 +      </listitem>
   1.191 +      <listitem><para>If you use the <command role="hg-cmd">hg
   1.192 +	    remove</command> command to remove a file, it will undo
   1.193 +	  the <quote>removed</quote> state of the file, and restore
   1.194 +	  the file to its unmodified contents.</para>
   1.195 +      </listitem></itemizedlist>
   1.196 +
   1.197 +    <sect2 id="sec:undo:mgmt">
   1.198 +      <title>File management errors</title>
   1.199 +
   1.200 +      <para>The <command role="hg-cmd">hg revert</command> command is
   1.201 +	useful for more than just modified files.  It lets you reverse
   1.202 +	the results of all of Mercurial's file management
   1.203 +	commands&emdash;<command role="hg-cmd">hg add</command>,
   1.204 +	<command role="hg-cmd">hg remove</command>, and so on.</para>
   1.205 +
   1.206 +      <para>If you <command role="hg-cmd">hg add</command> a file,
   1.207 +	then decide that in fact you don't want Mercurial to track it,
   1.208 +	use <command role="hg-cmd">hg revert</command> to undo the
   1.209 +	add.  Don't worry; Mercurial will not modify the file in any
   1.210 +	way.  It will just <quote>unmark</quote> the file. <!--
   1.211 +	&interaction.daily.revert.add; --></para>
   1.212 +
   1.213 +      <para>Similarly, if you ask Mercurial to <command
   1.214 +	  role="hg-cmd">hg remove</command> a file, you can use
   1.215 +	<command role="hg-cmd">hg revert</command> to restore it to
   1.216 +	the contents it had as of the parent of the working directory.
   1.217 +	<!-- &interaction.daily.revert.remove; --> This works just as
   1.218 +	well for a file that you deleted by hand, without telling
   1.219 +	Mercurial (recall that in Mercurial terminology, this kind of
   1.220 +	file is called <quote>missing</quote>). <!--
   1.221 +	&interaction.daily.revert.missing; --></para>
   1.222 +
   1.223 +      <para>If you revert a <command role="hg-cmd">hg copy</command>,
   1.224 +	the copied-to file remains in your working directory
   1.225 +	afterwards, untracked.  Since a copy doesn't affect the
   1.226 +	copied-from file in any way, Mercurial doesn't do anything
   1.227 +	with the copied-from file. <!--
   1.228 +	&interaction.daily.revert.copy; --></para>
   1.229 +
   1.230 +      <sect3>
   1.231 +	<title>A slightly special case: reverting a rename</title>
   1.232 +
   1.233 +	<para>If you <command role="hg-cmd">hg rename</command> a
   1.234 +	  file, there is one small detail that you should remember.
   1.235 +	  When you <command role="hg-cmd">hg revert</command> a
   1.236 +	  rename, it's not enough to provide the name of the
   1.237 +	  renamed-to file, as you can see here. <!--
   1.238 +	  &interaction.daily.revert.rename; --> As you can see from
   1.239 +	  the output of <command role="hg-cmd">hg status</command>,
   1.240 +	  the renamed-to file is no longer identified as added, but
   1.241 +	  the renamed-<emphasis>from</emphasis> file is still removed!
   1.242 +	  This is counter-intuitive (at least to me), but at least
   1.243 +	  it's easy to deal with. <!--
   1.244 +	  &interaction.daily.revert.rename-orig; --> So remember, to
   1.245 +	  revert a <command role="hg-cmd">hg rename</command>, you
   1.246 +	  must provide <emphasis>both</emphasis> the source and
   1.247 +	  destination names.</para>
   1.248 +
   1.249 +	<para>% TODO: the output doesn't look like it will be
   1.250 +	  removed!</para>
   1.251 +
   1.252 +	<para>(By the way, if you rename a file, then modify the
   1.253 +	  renamed-to file, then revert both components of the rename,
   1.254 +	  when Mercurial restores the file that was removed as part of
   1.255 +	  the rename, it will be unmodified. If you need the
   1.256 +	  modifications in the renamed-to file to show up in the
   1.257 +	  renamed-from file, don't forget to copy them over.)</para>
   1.258 +
   1.259 +	<para>These fiddly aspects of reverting a rename arguably
   1.260 +	  constitute a small bug in Mercurial.</para>
   1.261 +
   1.262 +      </sect3>
   1.263 +    </sect2>
   1.264 +  </sect1>
   1.265 +  <sect1>
   1.266 +    <title>Dealing with committed changes</title>
   1.267 +
   1.268 +    <para>Consider a case where you have committed a change $a$, and
   1.269 +      another change $b$ on top of it; you then realise that change
   1.270 +      $a$ was incorrect.  Mercurial lets you <quote>back out</quote>
   1.271 +      an entire changeset automatically, and building blocks that let
   1.272 +      you reverse part of a changeset by hand.</para>
   1.273 +
   1.274 +    <para>Before you read this section, here's something to keep in
   1.275 +      mind: the <command role="hg-cmd">hg backout</command> command
   1.276 +      undoes changes by <emphasis>adding</emphasis> history, not by
   1.277 +      modifying or erasing it.  It's the right tool to use if you're
   1.278 +      fixing bugs, but not if you're trying to undo some change that
   1.279 +      has catastrophic consequences.  To deal with those, see section
   1.280 +      <xref linkend="sec:undo:aaaiiieee"/>.</para>
   1.281 +
   1.282 +    <sect2>
   1.283 +      <title>Backing out a changeset</title>
   1.284 +
   1.285 +      <para>The <command role="hg-cmd">hg backout</command> command
   1.286 +	lets you <quote>undo</quote> the effects of an entire
   1.287 +	changeset in an automated fashion.  Because Mercurial's
   1.288 +	history is immutable, this command <emphasis>does
   1.289 +	  not</emphasis> get rid of the changeset you want to undo.
   1.290 +	Instead, it creates a new changeset that
   1.291 +	<emphasis>reverses</emphasis> the effect of the to-be-undone
   1.292 +	changeset.</para>
   1.293 +
   1.294 +      <para>The operation of the <command role="hg-cmd">hg
   1.295 +	  backout</command> command is a little intricate, so let's
   1.296 +	illustrate it with some examples.  First, we'll create a
   1.297 +	repository with some simple changes. <!--
   1.298 +	&interaction.backout.init; --></para>
   1.299 +
   1.300 +      <para>The <command role="hg-cmd">hg backout</command> command
   1.301 +	takes a single changeset ID as its argument; this is the
   1.302 +	changeset to back out.  Normally, <command role="hg-cmd">hg
   1.303 +	  backout</command> will drop you into a text editor to write
   1.304 +	a commit message, so you can record why you're backing the
   1.305 +	change out.  In this example, we provide a commit message on
   1.306 +	the command line using the <option
   1.307 +	  role="hg-opt-backout">-m</option> option.</para>
   1.308 +
   1.309 +    </sect2>
   1.310 +    <sect2>
   1.311 +      <title>Backing out the tip changeset</title>
   1.312 +
   1.313 +      <para>We're going to start by backing out the last changeset we
   1.314 +	committed. <!-- &interaction.backout.simple; --> You can see
   1.315 +	that the second line from <filename>myfile</filename> is no
   1.316 +	longer present.  Taking a look at the output of <command
   1.317 +	  role="hg-cmd">hg log</command> gives us an idea of what the
   1.318 +	<command role="hg-cmd">hg backout</command> command has done.
   1.319 +	<!-- &interaction.backout.simple.log; --> Notice that the new
   1.320 +	changeset that <command role="hg-cmd">hg backout</command> has
   1.321 +	created is a child of the changeset we backed out.  It's
   1.322 +	easier to see this in figure <xref
   1.323 +	  linkend="fig:undo:backout"/>, which presents a graphical
   1.324 +	view of the change history.  As you can see, the history is
   1.325 +	nice and linear.</para>
   1.326 +
   1.327 +      <informalfigure id="fig:undo:backout">
   1.328 +	<mediaobject><imageobject><imagedata
   1.329 +				    fileref="undo-simple"/></imageobject><textobject><phrase>XXX 
   1.330 +	      add text</phrase></textobject><caption><para>Backing out
   1.331 +	      a change using the <command role="hg-cmd">hg
   1.332 +		backout</command>
   1.333 +	      command</para></caption></mediaobject>
   1.334 +	
   1.335 +      </informalfigure>
   1.336 +
   1.337 +    </sect2>
   1.338 +    <sect2>
   1.339 +      <title>Backing out a non-tip change</title>
   1.340 +
   1.341 +      <para>If you want to back out a change other than the last one
   1.342 +	you committed, pass the <option
   1.343 +	  role="hg-opt-backout">--merge</option> option to the
   1.344 +	<command role="hg-cmd">hg backout</command> command. <!--
   1.345 +	&interaction.backout.non-tip.clone; --> This makes backing out
   1.346 +	any changeset a <quote>one-shot</quote> operation that's
   1.347 +	usually simple and fast. <!--
   1.348 +	&interaction.backout.non-tip.backout; --></para>
   1.349 +
   1.350 +      <para>If you take a look at the contents of
   1.351 +	<filename>myfile</filename> after the backout finishes, you'll
   1.352 +	see that the first and third changes are present, but not the
   1.353 +	second. <!-- &interaction.backout.non-tip.cat; --></para>
   1.354 +
   1.355 +      <para>As the graphical history in figure <xref
   1.356 +	  linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial
   1.357 +	actually commits <emphasis>two</emphasis> changes in this kind
   1.358 +	of situation (the box-shaped nodes are the ones that Mercurial
   1.359 +	commits automatically).  Before Mercurial begins the backout
   1.360 +	process, it first remembers what the current parent of the
   1.361 +	working directory is.  It then backs out the target changeset,
   1.362 +	and commits that as a changeset.  Finally, it merges back to
   1.363 +	the previous parent of the working directory, and commits the
   1.364 +	result of the merge.</para>
   1.365 +
   1.366 +      <para>% TODO: to me it looks like mercurial doesn't commit the
   1.367 +	second merge automatically!</para>
   1.368 +
   1.369 +      <informalfigure id="fig:undo:backout-non-tip">
   1.370 +	<mediaobject><imageobject><imagedata
   1.371 +				    fileref="undo-non-tip"/></imageobject><textobject><phrase>XXX 
   1.372 +	      add text</phrase></textobject><caption><para>Automated
   1.373 +	      backout of a non-tip change using the <command
   1.374 +		role="hg-cmd">hg backout</command>
   1.375 +	      command</para></caption></mediaobject>
   1.376 +      </informalfigure>
   1.377 +
   1.378 +      <para>The result is that you end up <quote>back where you
   1.379 +	  were</quote>, only with some extra history that undoes the
   1.380 +	effect of the changeset you wanted to back out.</para>
   1.381 +
   1.382 +      <sect3>
   1.383 +	<title>Always use the <option
   1.384 +	    role="hg-opt-backout">--merge</option> option</title>
   1.385 +
   1.386 +	<para>In fact, since the <option
   1.387 +	    role="hg-opt-backout">--merge</option> option will do the
   1.388 +	  <quote>right thing</quote> whether or not the changeset
   1.389 +	  you're backing out is the tip (i.e. it won't try to merge if
   1.390 +	  it's backing out the tip, since there's no need), you should
   1.391 +	  <emphasis>always</emphasis> use this option when you run the
   1.392 +	  <command role="hg-cmd">hg backout</command> command.</para>
   1.393 +
   1.394 +      </sect3>
   1.395 +    </sect2>
   1.396 +    <sect2>
   1.397 +      <title>Gaining more control of the backout process</title>
   1.398 +
   1.399 +      <para>While I've recommended that you always use the <option
   1.400 +	  role="hg-opt-backout">--merge</option> option when backing
   1.401 +	out a change, the <command role="hg-cmd">hg backout</command>
   1.402 +	command lets you decide how to merge a backout changeset.
   1.403 +	Taking control of the backout process by hand is something you
   1.404 +	will rarely need to do, but it can be useful to understand
   1.405 +	what the <command role="hg-cmd">hg backout</command> command
   1.406 +	is doing for you automatically.  To illustrate this, let's
   1.407 +	clone our first repository, but omit the backout change that
   1.408 +	it contains.</para>
   1.409 +
   1.410 +      <para><!-- &interaction.backout.manual.clone; --> As with our
   1.411 +	earlier example, We'll commit a third changeset, then back out
   1.412 +	its parent, and see what happens. <!--
   1.413 +	&interaction.backout.manual.backout; --> Our new changeset is
   1.414 +	again a descendant of the changeset we backout out; it's thus
   1.415 +	a new head, <emphasis>not</emphasis> a descendant of the
   1.416 +	changeset that was the tip.  The <command role="hg-cmd">hg
   1.417 +	  backout</command> command was quite explicit in telling us
   1.418 +	this. <!-- &interaction.backout.manual.log; --></para>
   1.419 +
   1.420 +      <para>Again, it's easier to see what has happened by looking at
   1.421 +	a graph of the revision history, in figure <xref
   1.422 +	  linkend="fig:undo:backout-manual"/>.  This makes it clear
   1.423 +	that when we use <command role="hg-cmd">hg backout</command>
   1.424 +	to back out a change other than the tip, Mercurial adds a new
   1.425 +	head to the repository (the change it committed is
   1.426 +	box-shaped).</para>
   1.427 +
   1.428 +      <informalfigure id="fig:undo:backout-manual">
   1.429 +	<mediaobject><imageobject><imagedata
   1.430 +				    fileref="undo-manual"/></imageobject><textobject><phrase>XXX 
   1.431 +	      add text</phrase></textobject><caption><para>Backing out
   1.432 +	      a change using the <command role="hg-cmd">hg
   1.433 +		backout</command>
   1.434 +	      command</para></caption></mediaobject>
   1.435 +	
   1.436 +      </informalfigure>
   1.437 +
   1.438 +      <para>After the <command role="hg-cmd">hg backout</command>
   1.439 +	command has completed, it leaves the new
   1.440 +	<quote>backout</quote> changeset as the parent of the working
   1.441 +	directory. <!-- &interaction.backout.manual.parents; --> Now
   1.442 +	we have two isolated sets of changes. <!--
   1.443 +	&interaction.backout.manual.heads; --></para>
   1.444 +
   1.445 +      <para>Let's think about what we expect to see as the contents of
   1.446 +	<filename>myfile</filename> now.  The first change should be
   1.447 +	present, because we've never backed it out.  The second change
   1.448 +	should be missing, as that's the change we backed out.  Since
   1.449 +	the history graph shows the third change as a separate head,
   1.450 +	we <emphasis>don't</emphasis> expect to see the third change
   1.451 +	present in <filename>myfile</filename>. <!--
   1.452 +	&interaction.backout.manual.cat; --> To get the third change
   1.453 +	back into the file, we just do a normal merge of our two
   1.454 +	heads. <!-- &interaction.backout.manual.merge; --> Afterwards,
   1.455 +	the graphical history of our repository looks like figure
   1.456 +	<xref linkend="fig:undo:backout-manual-merge"/>.</para>
   1.457 +
   1.458 +      <informalfigure id="fig:undo:backout-manual-merge">
   1.459 +	<mediaobject><imageobject><imagedata
   1.460 +				    fileref="undo-manual-merge"/></imageobject><textobject><phrase>XXX 
   1.461 +	      add text</phrase></textobject><caption><para>Manually
   1.462 +	      merging a backout change</para></caption></mediaobject>
   1.463 +	
   1.464 +      </informalfigure>
   1.465 +
   1.466 +    </sect2>
   1.467 +    <sect2>
   1.468 +      <title>Why <command role="hg-cmd">hg backout</command> works as
   1.469 +	it does</title>
   1.470 +
   1.471 +      <para>Here's a brief description of how the <command
   1.472 +	  role="hg-cmd">hg backout</command> command works.</para>
   1.473 +      <orderedlist>
   1.474 +	<listitem><para>It ensures that the working directory is
   1.475 +	    <quote>clean</quote>, i.e. that the output of <command
   1.476 +	      role="hg-cmd">hg status</command> would be empty.</para>
   1.477 +	</listitem>
   1.478 +	<listitem><para>It remembers the current parent of the working
   1.479 +	    directory.  Let's call this changeset
   1.480 +	    <literal>orig</literal></para>
   1.481 +	</listitem>
   1.482 +	<listitem><para>It does the equivalent of a <command
   1.483 +	      role="hg-cmd">hg update</command> to sync the working
   1.484 +	    directory to the changeset you want to back out.  Let's
   1.485 +	    call this changeset <literal>backout</literal></para>
   1.486 +	</listitem>
   1.487 +	<listitem><para>It finds the parent of that changeset.  Let's
   1.488 +	    call that changeset <literal>parent</literal>.</para>
   1.489 +	</listitem>
   1.490 +	<listitem><para>For each file that the
   1.491 +	    <literal>backout</literal> changeset affected, it does the
   1.492 +	    equivalent of a <command role="hg-cmd">hg revert -r
   1.493 +	      parent</command> on that file, to restore it to the
   1.494 +	    contents it had before that changeset was
   1.495 +	    committed.</para>
   1.496 +	</listitem>
   1.497 +	<listitem><para>It commits the result as a new changeset.
   1.498 +	    This changeset has <literal>backout</literal> as its
   1.499 +	    parent.</para>
   1.500 +	</listitem>
   1.501 +	<listitem><para>If you specify <option
   1.502 +	      role="hg-opt-backout">--merge</option> on the command
   1.503 +	    line, it merges with <literal>orig</literal>, and commits
   1.504 +	    the result of the merge.</para>
   1.505 +	</listitem></orderedlist>
   1.506 +
   1.507 +      <para>An alternative way to implement the <command
   1.508 +	  role="hg-cmd">hg backout</command> command would be to
   1.509 +	<command role="hg-cmd">hg export</command> the
   1.510 +	to-be-backed-out changeset as a diff, then use the <option
   1.511 +	  role="cmd-opt-patch">--reverse</option> option to the
   1.512 +	<command>patch</command> command to reverse the effect of the
   1.513 +	change without fiddling with the working directory.  This
   1.514 +	sounds much simpler, but it would not work nearly as
   1.515 +	well.</para>
   1.516 +
   1.517 +      <para>The reason that <command role="hg-cmd">hg
   1.518 +	  backout</command> does an update, a commit, a merge, and
   1.519 +	another commit is to give the merge machinery the best chance
   1.520 +	to do a good job when dealing with all the changes
   1.521 +	<emphasis>between</emphasis> the change you're backing out and
   1.522 +	the current tip.</para>
   1.523 +
   1.524 +      <para>If you're backing out a changeset that's 100 revisions
   1.525 +	back in your project's history, the chances that the
   1.526 +	<command>patch</command> command will be able to apply a
   1.527 +	reverse diff cleanly are not good, because intervening changes
   1.528 +	are likely to have <quote>broken the context</quote> that
   1.529 +	<command>patch</command> uses to determine whether it can
   1.530 +	apply a patch (if this sounds like gibberish, see <xref
   1.531 +	  linkend="sec:mq:patch"/> for a
   1.532 +	discussion of the <command>patch</command> command).  Also,
   1.533 +	Mercurial's merge machinery will handle files and directories
   1.534 +	being renamed, permission changes, and modifications to binary
   1.535 +	files, none of which <command>patch</command> can deal
   1.536 +	with.</para>
   1.537 +
   1.538 +    </sect2>
   1.539 +  </sect1>
   1.540 +  <sect1 id="sec:undo:aaaiiieee">
   1.541 +    <title>Changes that should never have been</title>
   1.542 +
   1.543 +    <para>Most of the time, the <command role="hg-cmd">hg
   1.544 +	backout</command> command is exactly what you need if you want
   1.545 +      to undo the effects of a change.  It leaves a permanent record
   1.546 +      of exactly what you did, both when committing the original
   1.547 +      changeset and when you cleaned up after it.</para>
   1.548 +
   1.549 +    <para>On rare occasions, though, you may find that you've
   1.550 +      committed a change that really should not be present in the
   1.551 +      repository at all.  For example, it would be very unusual, and
   1.552 +      usually considered a mistake, to commit a software project's
   1.553 +      object files as well as its source files.  Object files have
   1.554 +      almost no intrinsic value, and they're <emphasis>big</emphasis>,
   1.555 +      so they increase the size of the repository and the amount of
   1.556 +      time it takes to clone or pull changes.</para>
   1.557 +
   1.558 +    <para>Before I discuss the options that you have if you commit a
   1.559 +      <quote>brown paper bag</quote> change (the kind that's so bad
   1.560 +      that you want to pull a brown paper bag over your head), let me
   1.561 +      first discuss some approaches that probably won't work.</para>
   1.562 +
   1.563 +    <para>Since Mercurial treats history as accumulative&emdash;every
   1.564 +      change builds on top of all changes that preceded it&emdash;you
   1.565 +      generally can't just make disastrous changes disappear.  The one
   1.566 +      exception is when you've just committed a change, and it hasn't
   1.567 +      been pushed or pulled into another repository.  That's when you
   1.568 +      can safely use the <command role="hg-cmd">hg rollback</command>
   1.569 +      command, as I detailed in section <xref
   1.570 +	linkend="sec:undo:rollback"/>.</para>
   1.571 +
   1.572 +    <para>After you've pushed a bad change to another repository, you
   1.573 +      <emphasis>could</emphasis> still use <command role="hg-cmd">hg
   1.574 +	rollback</command> to make your local copy of the change
   1.575 +      disappear, but it won't have the consequences you want.  The
   1.576 +      change will still be present in the remote repository, so it
   1.577 +      will reappear in your local repository the next time you
   1.578 +      pull.</para>
   1.579 +
   1.580 +    <para>If a situation like this arises, and you know which
   1.581 +      repositories your bad change has propagated into, you can
   1.582 +      <emphasis>try</emphasis> to get rid of the changeefrom
   1.583 +      <emphasis>every</emphasis> one of those repositories.  This is,
   1.584 +      of course, not a satisfactory solution: if you miss even a
   1.585 +      single repository while you're expunging, the change is still
   1.586 +      <quote>in the wild</quote>, and could propagate further.</para>
   1.587 +
   1.588 +    <para>If you've committed one or more changes
   1.589 +      <emphasis>after</emphasis> the change that you'd like to see
   1.590 +      disappear, your options are further reduced. Mercurial doesn't
   1.591 +      provide a way to <quote>punch a hole</quote> in history, leaving
   1.592 +      changesets intact.</para>
   1.593 +
   1.594 +    <para>XXX This needs filling out.  The
   1.595 +      <literal>hg-replay</literal> script in the
   1.596 +      <literal>examples</literal> directory works, but doesn't handle
   1.597 +      merge changesets.  Kind of an important omission.</para>
   1.598 +
   1.599 +    <sect2>
   1.600 +      <title>Protect yourself from <quote>escaped</quote>
   1.601 +	changes</title>
   1.602 +
   1.603 +      <para>If you've committed some changes to your local repository
   1.604 +	and they've been pushed or pulled somewhere else, this isn't
   1.605 +	necessarily a disaster.  You can protect yourself ahead of
   1.606 +	time against some classes of bad changeset.  This is
   1.607 +	particularly easy if your team usually pulls changes from a
   1.608 +	central repository.</para>
   1.609 +
   1.610 +      <para>By configuring some hooks on that repository to validate
   1.611 +	incoming changesets (see chapter <xref linkend="chap:hook"/>),
   1.612 +	you can
   1.613 +	automatically prevent some kinds of bad changeset from being
   1.614 +	pushed to the central repository at all.  With such a
   1.615 +	configuration in place, some kinds of bad changeset will
   1.616 +	naturally tend to <quote>die out</quote> because they can't
   1.617 +	propagate into the central repository.  Better yet, this
   1.618 +	happens without any need for explicit intervention.</para>
   1.619 +
   1.620 +      <para>For instance, an incoming change hook that verifies that a
   1.621 +	changeset will actually compile can prevent people from
   1.622 +	inadvertantly <quote>breaking the build</quote>.</para>
   1.623 +
   1.624 +    </sect2>
   1.625 +  </sect1>
   1.626 +  <sect1 id="sec:undo:bisect">
   1.627 +    <title>Finding the source of a bug</title>
   1.628 +
   1.629 +    <para>While it's all very well to be able to back out a changeset
   1.630 +      that introduced a bug, this requires that you know which
   1.631 +      changeset to back out.  Mercurial provides an invaluable
   1.632 +      command, called <command role="hg-cmd">hg bisect</command>, that
   1.633 +      helps you to automate this process and accomplish it very
   1.634 +      efficiently.</para>
   1.635 +
   1.636 +    <para>The idea behind the <command role="hg-cmd">hg
   1.637 +	bisect</command> command is that a changeset has introduced
   1.638 +      some change of behaviour that you can identify with a simple
   1.639 +      binary test.  You don't know which piece of code introduced the
   1.640 +      change, but you know how to test for the presence of the bug.
   1.641 +      The <command role="hg-cmd">hg bisect</command> command uses your
   1.642 +      test to direct its search for the changeset that introduced the
   1.643 +      code that caused the bug.</para>
   1.644 +
   1.645 +    <para>Here are a few scenarios to help you understand how you
   1.646 +      might apply this command.</para>
   1.647 +    <itemizedlist>
   1.648 +      <listitem><para>The most recent version of your software has a
   1.649 +	  bug that you remember wasn't present a few weeks ago, but
   1.650 +	  you don't know when it was introduced.  Here, your binary
   1.651 +	  test checks for the presence of that bug.</para>
   1.652 +      </listitem>
   1.653 +      <listitem><para>You fixed a bug in a rush, and now it's time to
   1.654 +	  close the entry in your team's bug database.  The bug
   1.655 +	  database requires a changeset ID when you close an entry,
   1.656 +	  but you don't remember which changeset you fixed the bug in.
   1.657 +	  Once again, your binary test checks for the presence of the
   1.658 +	  bug.</para>
   1.659 +      </listitem>
   1.660 +      <listitem><para>Your software works correctly, but runs 15%
   1.661 +	  slower than the last time you measured it.  You want to know
   1.662 +	  which changeset introduced the performance regression.  In
   1.663 +	  this case, your binary test measures the performance of your
   1.664 +	  software, to see whether it's <quote>fast</quote> or
   1.665 +	  <quote>slow</quote>.</para>
   1.666 +      </listitem>
   1.667 +      <listitem><para>The sizes of the components of your project that
   1.668 +	  you ship exploded recently, and you suspect that something
   1.669 +	  changed in the way you build your project.</para>
   1.670 +      </listitem></itemizedlist>
   1.671 +
   1.672 +    <para>From these examples, it should be clear that the <command
   1.673 +	role="hg-cmd">hg bisect</command> command is not useful only
   1.674 +      for finding the sources of bugs.  You can use it to find any
   1.675 +      <quote>emergent property</quote> of a repository (anything that
   1.676 +      you can't find from a simple text search of the files in the
   1.677 +      tree) for which you can write a binary test.</para>
   1.678 +
   1.679 +    <para>We'll introduce a little bit of terminology here, just to
   1.680 +      make it clear which parts of the search process are your
   1.681 +      responsibility, and which are Mercurial's.  A
   1.682 +      <emphasis>test</emphasis> is something that
   1.683 +      <emphasis>you</emphasis> run when <command role="hg-cmd">hg
   1.684 +	bisect</command> chooses a changeset.  A
   1.685 +      <emphasis>probe</emphasis> is what <command role="hg-cmd">hg
   1.686 +	bisect</command> runs to tell whether a revision is good.
   1.687 +      Finally, we'll use the word <quote>bisect</quote>, as both a
   1.688 +      noun and a verb, to stand in for the phrase <quote>search using
   1.689 +	the <command role="hg-cmd">hg bisect</command>
   1.690 +	command</quote>.</para>
   1.691 +
   1.692 +    <para>One simple way to automate the searching process would be
   1.693 +      simply to probe every changeset.  However, this scales poorly.
   1.694 +      If it took ten minutes to test a single changeset, and you had
   1.695 +      10,000 changesets in your repository, the exhaustive approach
   1.696 +      would take on average 35 <emphasis>days</emphasis> to find the
   1.697 +      changeset that introduced a bug.  Even if you knew that the bug
   1.698 +      was introduced by one of the last 500 changesets, and limited
   1.699 +      your search to those, you'd still be looking at over 40 hours to
   1.700 +      find the changeset that introduced your bug.</para>
   1.701 +
   1.702 +    <para>What the <command role="hg-cmd">hg bisect</command> command
   1.703 +      does is use its knowledge of the <quote>shape</quote> of your
   1.704 +      project's revision history to perform a search in time
   1.705 +      proportional to the <emphasis>logarithm</emphasis> of the number
   1.706 +      of changesets to check (the kind of search it performs is called
   1.707 +      a dichotomic search).  With this approach, searching through
   1.708 +      10,000 changesets will take less than three hours, even at ten
   1.709 +      minutes per test (the search will require about 14 tests).
   1.710 +      Limit your search to the last hundred changesets, and it will
   1.711 +      take only about an hour (roughly seven tests).</para>
   1.712 +
   1.713 +    <para>The <command role="hg-cmd">hg bisect</command> command is
   1.714 +      aware of the <quote>branchy</quote> nature of a Mercurial
   1.715 +      project's revision history, so it has no problems dealing with
   1.716 +      branches, merges, or multiple heads in a repository.  It can
   1.717 +      prune entire branches of history with a single probe, which is
   1.718 +      how it operates so efficiently.</para>
   1.719 +
   1.720 +    <sect2>
   1.721 +      <title>Using the <command role="hg-cmd">hg bisect</command>
   1.722 +	command</title>
   1.723 +
   1.724 +      <para>Here's an example of <command role="hg-cmd">hg
   1.725 +	  bisect</command> in action.</para>
   1.726 +
   1.727 +      <note>
   1.728 +	<para>  In versions 0.9.5 and earlier of Mercurial, <command
   1.729 +	    role="hg-cmd">hg bisect</command> was not a core command:
   1.730 +	  it was distributed with Mercurial as an extension. This
   1.731 +	  section describes the built-in command, not the old
   1.732 +	  extension.</para>
   1.733 +      </note>
   1.734 +
   1.735 +      <para>Now let's create a repository, so that we can try out the
   1.736 +	<command role="hg-cmd">hg bisect</command> command in
   1.737 +	isolation. <!-- &interaction.bisect.init; --> We'll simulate a
   1.738 +	project that has a bug in it in a simple-minded way: create
   1.739 +	trivial changes in a loop, and nominate one specific change
   1.740 +	that will have the <quote>bug</quote>.  This loop creates 35
   1.741 +	changesets, each adding a single file to the repository.
   1.742 +	We'll represent our <quote>bug</quote> with a file that
   1.743 +	contains the text <quote>i have a gub</quote>. <!--
   1.744 +	&interaction.bisect.commits; --></para>
   1.745 +
   1.746 +      <para>The next thing that we'd like to do is figure out how to
   1.747 +	use the <command role="hg-cmd">hg bisect</command> command.
   1.748 +	We can use Mercurial's normal built-in help mechanism for
   1.749 +	this. <!-- &interaction.bisect.help; --></para>
   1.750 +
   1.751 +      <para>The <command role="hg-cmd">hg bisect</command> command
   1.752 +	works in steps.  Each step proceeds as follows.</para>
   1.753 +      <orderedlist>
   1.754 +	<listitem><para>You run your binary test.</para>
   1.755 +	  <itemizedlist>
   1.756 +	    <listitem><para>If the test succeeded, you tell <command
   1.757 +		  role="hg-cmd">hg bisect</command> by running the
   1.758 +		<command role="hg-cmd">hg bisect good</command>
   1.759 +		command.</para>
   1.760 +	    </listitem>
   1.761 +	    <listitem><para>If it failed, run the <command
   1.762 +		  role="hg-cmd">hg bisect bad</command>
   1.763 +		command.</para></listitem></itemizedlist>
   1.764 +	</listitem>
   1.765 +	<listitem><para>The command uses your information to decide
   1.766 +	    which changeset to test next.</para>
   1.767 +	</listitem>
   1.768 +	<listitem><para>It updates the working directory to that
   1.769 +	    changeset, and the process begins again.</para>
   1.770 +	</listitem></orderedlist>
   1.771 +      <para>The process ends when <command role="hg-cmd">hg
   1.772 +	  bisect</command> identifies a unique changeset that marks
   1.773 +	the point where your test transitioned from
   1.774 +	<quote>succeeding</quote> to <quote>failing</quote>.</para>
   1.775 +
   1.776 +      <para>To start the search, we must run the <command
   1.777 +	  role="hg-cmd">hg bisect --reset</command> command. <!--
   1.778 +	&interaction.bisect.search.init; --></para>
   1.779 +
   1.780 +      <para>In our case, the binary test we use is simple: we check to
   1.781 +	see if any file in the repository contains the string <quote>i
   1.782 +	  have a gub</quote>.  If it does, this changeset contains the
   1.783 +	change that <quote>caused the bug</quote>.  By convention, a
   1.784 +	changeset that has the property we're searching for is
   1.785 +	<quote>bad</quote>, while one that doesn't is
   1.786 +	<quote>good</quote>.</para>
   1.787 +
   1.788 +      <para>Most of the time, the revision to which the working
   1.789 +	directory is synced (usually the tip) already exhibits the
   1.790 +	problem introduced by the buggy change, so we'll mark it as
   1.791 +	<quote>bad</quote>. <!-- &interaction.bisect.search.bad-init;
   1.792 +	--></para>
   1.793 +
   1.794 +      <para>Our next task is to nominate a changeset that we know
   1.795 +	<emphasis>doesn't</emphasis> have the bug; the <command
   1.796 +	  role="hg-cmd">hg bisect</command> command will
   1.797 +	<quote>bracket</quote> its search between the first pair of
   1.798 +	good and bad changesets.  In our case, we know that revision
   1.799 +	10 didn't have the bug.  (I'll have more words about choosing
   1.800 +	the first <quote>good</quote> changeset later.) <!--
   1.801 +	&interaction.bisect.search.good-init; --></para>
   1.802 +
   1.803 +      <para>Notice that this command printed some output.</para>
   1.804 +      <itemizedlist>
   1.805 +	<listitem><para>It told us how many changesets it must
   1.806 +	    consider before it can identify the one that introduced
   1.807 +	    the bug, and how many tests that will require.</para>
   1.808 +	</listitem>
   1.809 +	<listitem><para>It updated the working directory to the next
   1.810 +	    changeset to test, and told us which changeset it's
   1.811 +	    testing.</para>
   1.812 +	</listitem></itemizedlist>
   1.813 +
   1.814 +      <para>We now run our test in the working directory.  We use the
   1.815 +	<command>grep</command> command to see if our
   1.816 +	<quote>bad</quote> file is present in the working directory.
   1.817 +	If it is, this revision is bad; if not, this revision is good.
   1.818 +	<!-- &interaction.bisect.search.step1; --></para>
   1.819 +
   1.820 +      <para>This test looks like a perfect candidate for automation,
   1.821 +	so let's turn it into a shell function. <!--
   1.822 +	&interaction.bisect.search.mytest; --> We can now run an
   1.823 +	entire test step with a single command,
   1.824 +	<literal>mytest</literal>. <!--
   1.825 +	&interaction.bisect.search.step2; --> A few more invocations
   1.826 +	of our canned test step command, and we're done. <!--
   1.827 +	&interaction.bisect.search.rest; --></para>
   1.828 +
   1.829 +      <para>Even though we had 40 changesets to search through, the
   1.830 +	<command role="hg-cmd">hg bisect</command> command let us find
   1.831 +	the changeset that introduced our <quote>bug</quote> with only
   1.832 +	five tests.  Because the number of tests that the <command
   1.833 +	  role="hg-cmd">hg bisect</command> command performs grows
   1.834 +	logarithmically with the number of changesets to search, the
   1.835 +	advantage that it has over the <quote>brute force</quote>
   1.836 +	search approach increases with every changeset you add.</para>
   1.837 +
   1.838 +    </sect2>
   1.839 +    <sect2>
   1.840 +      <title>Cleaning up after your search</title>
   1.841 +
   1.842 +      <para>When you're finished using the <command role="hg-cmd">hg
   1.843 +	  bisect</command> command in a repository, you can use the
   1.844 +	<command role="hg-cmd">hg bisect reset</command> command to
   1.845 +	drop the information it was using to drive your search.  The
   1.846 +	command doesn't use much space, so it doesn't matter if you
   1.847 +	forget to run this command.  However, <command
   1.848 +	  role="hg-cmd">hg bisect</command> won't let you start a new
   1.849 +	search in that repository until you do a <command
   1.850 +	  role="hg-cmd">hg bisect reset</command>. <!--
   1.851 +	&interaction.bisect.search.reset; --></para>
   1.852 +
   1.853 +    </sect2>
   1.854 +  </sect1>
   1.855 +  <sect1>
   1.856 +    <title>Tips for finding bugs effectively</title>
   1.857 +
   1.858 +    <sect2>
   1.859 +      <title>Give consistent input</title>
   1.860 +
   1.861 +      <para>The <command role="hg-cmd">hg bisect</command> command
   1.862 +	requires that you correctly report the result of every test
   1.863 +	you perform.  If you tell it that a test failed when it really
   1.864 +	succeeded, it <emphasis>might</emphasis> be able to detect the
   1.865 +	inconsistency.  If it can identify an inconsistency in your
   1.866 +	reports, it will tell you that a particular changeset is both
   1.867 +	good and bad. However, it can't do this perfectly; it's about
   1.868 +	as likely to report the wrong changeset as the source of the
   1.869 +	bug.</para>
   1.870 +
   1.871 +    </sect2>
   1.872 +    <sect2>
   1.873 +      <title>Automate as much as possible</title>
   1.874 +
   1.875 +      <para>When I started using the <command role="hg-cmd">hg
   1.876 +	  bisect</command> command, I tried a few times to run my
   1.877 +	tests by hand, on the command line.  This is an approach that
   1.878 +	I, at least, am not suited to.  After a few tries, I found
   1.879 +	that I was making enough mistakes that I was having to restart
   1.880 +	my searches several times before finally getting correct
   1.881 +	results.</para>
   1.882 +
   1.883 +      <para>My initial problems with driving the <command
   1.884 +	  role="hg-cmd">hg bisect</command> command by hand occurred
   1.885 +	even with simple searches on small repositories; if the
   1.886 +	problem you're looking for is more subtle, or the number of
   1.887 +	tests that <command role="hg-cmd">hg bisect</command> must
   1.888 +	perform increases, the likelihood of operator error ruining
   1.889 +	the search is much higher.  Once I started automating my
   1.890 +	tests, I had much better results.</para>
   1.891 +
   1.892 +      <para>The key to automated testing is twofold:</para>
   1.893 +      <itemizedlist>
   1.894 +	<listitem><para>always test for the same symptom, and</para>
   1.895 +	</listitem>
   1.896 +	<listitem><para>always feed consistent input to the <command
   1.897 +	      role="hg-cmd">hg bisect</command> command.</para>
   1.898 +	</listitem></itemizedlist>
   1.899 +      <para>In my tutorial example above, the <command>grep</command>
   1.900 +	command tests for the symptom, and the <literal>if</literal>
   1.901 +	statement takes the result of this check and ensures that we
   1.902 +	always feed the same input to the <command role="hg-cmd">hg
   1.903 +	  bisect</command> command.  The <literal>mytest</literal>
   1.904 +	function marries these together in a reproducible way, so that
   1.905 +	every test is uniform and consistent.</para>
   1.906 +
   1.907 +    </sect2>
   1.908 +    <sect2>
   1.909 +      <title>Check your results</title>
   1.910 +
   1.911 +      <para>Because the output of a <command role="hg-cmd">hg
   1.912 +	  bisect</command> search is only as good as the input you
   1.913 +	give it, don't take the changeset it reports as the absolute
   1.914 +	truth.  A simple way to cross-check its report is to manually
   1.915 +	run your test at each of the following changesets:</para>
   1.916 +      <itemizedlist>
   1.917 +	<listitem><para>The changeset that it reports as the first bad
   1.918 +	    revision.  Your test should still report this as
   1.919 +	    bad.</para>
   1.920 +	</listitem>
   1.921 +	<listitem><para>The parent of that changeset (either parent,
   1.922 +	    if it's a merge). Your test should report this changeset
   1.923 +	    as good.</para>
   1.924 +	</listitem>
   1.925 +	<listitem><para>A child of that changeset.  Your test should
   1.926 +	    report this changeset as bad.</para>
   1.927 +	</listitem></itemizedlist>
   1.928 +
   1.929 +    </sect2>
   1.930 +    <sect2>
   1.931 +      <title>Beware interference between bugs</title>
   1.932 +
   1.933 +      <para>It's possible that your search for one bug could be
   1.934 +	disrupted by the presence of another.  For example, let's say
   1.935 +	your software crashes at revision 100, and worked correctly at
   1.936 +	revision 50.  Unknown to you, someone else introduced a
   1.937 +	different crashing bug at revision 60, and fixed it at
   1.938 +	revision 80.  This could distort your results in one of
   1.939 +	several ways.</para>
   1.940 +
   1.941 +      <para>It is possible that this other bug completely
   1.942 +	<quote>masks</quote> yours, which is to say that it occurs
   1.943 +	before your bug has a chance to manifest itself.  If you can't
   1.944 +	avoid that other bug (for example, it prevents your project
   1.945 +	from building), and so can't tell whether your bug is present
   1.946 +	in a particular changeset, the <command role="hg-cmd">hg
   1.947 +	  bisect</command> command cannot help you directly.  Instead,
   1.948 +	you can mark a changeset as untested by running <command
   1.949 +	  role="hg-cmd">hg bisect --skip</command>.</para>
   1.950 +
   1.951 +      <para>A different problem could arise if your test for a bug's
   1.952 +	presence is not specific enough.  If you check for <quote>my
   1.953 +	  program crashes</quote>, then both your crashing bug and an
   1.954 +	unrelated crashing bug that masks it will look like the same
   1.955 +	thing, and mislead <command role="hg-cmd">hg
   1.956 +	  bisect</command>.</para>
   1.957 +
   1.958 +      <para>Another useful situation in which to use <command
   1.959 +	  role="hg-cmd">hg bisect --skip</command> is if you can't
   1.960 +	test a revision because your project was in a broken and hence
   1.961 +	untestable state at that revision, perhaps because someone
   1.962 +	checked in a change that prevented the project from
   1.963 +	building.</para>
   1.964 +
   1.965 +    </sect2>
   1.966 +    <sect2>
   1.967 +      <title>Bracket your search lazily</title>
   1.968 +
   1.969 +      <para>Choosing the first <quote>good</quote> and
   1.970 +	<quote>bad</quote> changesets that will mark the end points of
   1.971 +	your search is often easy, but it bears a little discussion
   1.972 +	nevertheless.  From the perspective of <command
   1.973 +	  role="hg-cmd">hg bisect</command>, the <quote>newest</quote>
   1.974 +	changeset is conventionally <quote>bad</quote>, and the older
   1.975 +	changeset is <quote>good</quote>.</para>
   1.976 +
   1.977 +      <para>If you're having trouble remembering when a suitable
   1.978 +	<quote>good</quote> change was, so that you can tell <command
   1.979 +	  role="hg-cmd">hg bisect</command>, you could do worse than
   1.980 +	testing changesets at random.  Just remember to eliminate
   1.981 +	contenders that can't possibly exhibit the bug (perhaps
   1.982 +	because the feature with the bug isn't present yet) and those
   1.983 +	where another problem masks the bug (as I discussed
   1.984 +	above).</para>
   1.985 +
   1.986 +      <para>Even if you end up <quote>early</quote> by thousands of
   1.987 +	changesets or months of history, you will only add a handful
   1.988 +	of tests to the total number that <command role="hg-cmd">hg
   1.989 +	  bisect</command> must perform, thanks to its logarithmic
   1.990 +	behaviour.</para>
   1.991 +
   1.992 +    </sect2>
   1.993 +  </sect1>
   1.994 +</chapter>
   1.995 +
   1.996 +<!--
   1.997 +local variables: 
   1.998 +sgml-parent-document: ("00book.xml" "book" "chapter")
   1.999 +end:
  1.1000 +-->