hgbook

diff fr/ch09-undo.xml @ 964:6b680d569bb4

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