hgbook

diff en/ch09-undo.xml @ 977:719b03ea27c8

merge with Italian, and very (few) work on ch03
author Romain PELISSE <belaran@gmail.com>
date Fri Sep 04 16:33:46 2009 +0200 (2009-09-04)
parents 1a0a78e197c3
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/en/ch09-undo.xml	Fri Sep 04 16:33:46 2009 +0200
     1.3 @@ -0,0 +1,1201 @@
     1.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
     1.5 +
     1.6 +<chapter id="chap:undo">
     1.7 +  <?dbhtml filename="finding-and-fixing-mistakes.html"?>
     1.8 +  <title>Finding and fixing mistakes</title>
     1.9 +
    1.10 +  <para id="x_d2">To err might be human, but to really handle the consequences
    1.11 +    well takes a top-notch revision control system.  In this chapter,
    1.12 +    we'll discuss some of the techniques you can use when you find
    1.13 +    that a problem has crept into your project.  Mercurial has some
    1.14 +    highly capable features that will help you to isolate the sources
    1.15 +    of 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 id="x_d3">I have the occasional but persistent problem of typing
    1.24 +	rather more quickly than I can think, which sometimes results
    1.25 +	in me committing a changeset that is either incomplete or
    1.26 +	plain wrong.  In my case, the usual kind of incomplete
    1.27 +	changeset is one in which I've created a new source file, but
    1.28 +	forgotten to <command role="hg-cmd">hg add</command> it.  A
    1.29 +	<quote>plain wrong</quote> changeset is not as common, but no
    1.30 +	less annoying.</para>
    1.31 +
    1.32 +    </sect2>
    1.33 +    <sect2 id="sec:undo:rollback">
    1.34 +      <title>Rolling back a transaction</title>
    1.35 +
    1.36 +      <para id="x_d4">In <xref linkend="sec:concepts:txn"/>, I
    1.37 +	mentioned that Mercurial treats each modification of a
    1.38 +	repository as a <emphasis>transaction</emphasis>.  Every time
    1.39 +	you commit a changeset or pull changes from another
    1.40 +	repository, Mercurial remembers what you did.  You can undo,
    1.41 +	or <emphasis>roll back</emphasis>, exactly one of these
    1.42 +	actions using the <command role="hg-cmd">hg rollback</command>
    1.43 +	command.  (See <xref linkend="sec:undo:rollback-after-push"/>
    1.44 +	for an important caveat about the use of this command.)</para>
    1.45 +
    1.46 +      <para id="x_d5">Here's a mistake that I often find myself making:
    1.47 +	committing a change in which I've created a new file, but
    1.48 +	forgotten to <command role="hg-cmd">hg add</command>
    1.49 +	it.</para>
    1.50 +
    1.51 +      &interaction.rollback.commit;
    1.52 +
    1.53 +      <para id="x_d6">Looking at the output of <command role="hg-cmd">hg
    1.54 +	  status</command> after the commit immediately confirms the
    1.55 +	error.</para>
    1.56 +
    1.57 +      &interaction.rollback.status;
    1.58 +
    1.59 +      <para id="x_d7">The commit captured the changes to the file
    1.60 +	<filename>a</filename>, but not the new file
    1.61 +	<filename>b</filename>.  If I were to push this changeset to a
    1.62 +	repository that I shared with a colleague, the chances are
    1.63 +	high that something in <filename>a</filename> would refer to
    1.64 +	<filename>b</filename>, which would not be present in their
    1.65 +	repository when they pulled my changes.  I would thus become
    1.66 +	the object of some indignation.</para>
    1.67 +
    1.68 +      <para id="x_d8">However, luck is with me&emdash;I've caught my error
    1.69 +	before I pushed the changeset.  I use the <command
    1.70 +	  role="hg-cmd">hg rollback</command> command, and Mercurial
    1.71 +	makes that last changeset vanish.</para>
    1.72 +
    1.73 +      &interaction.rollback.rollback;
    1.74 +
    1.75 +      <para id="x_d9">Notice that the changeset is no longer present in the
    1.76 +	repository's history, and the working directory once again
    1.77 +	thinks that the file <filename>a</filename> is modified.  The
    1.78 +	commit and rollback have left the working directory exactly as
    1.79 +	it was prior to the commit; the changeset has been completely
    1.80 +	erased.  I can now safely <command role="hg-cmd">hg
    1.81 +	  add</command> the file <filename>b</filename>, and rerun my
    1.82 +	commit.</para>
    1.83 +
    1.84 +      &interaction.rollback.add;
    1.85 +
    1.86 +    </sect2>
    1.87 +    <sect2>
    1.88 +      <title>The erroneous pull</title>
    1.89 +
    1.90 +      <para id="x_da">It's common practice with Mercurial to maintain separate
    1.91 +	development branches of a project in different repositories.
    1.92 +	Your development team might have one shared repository for
    1.93 +	your project's <quote>0.9</quote> release, and another,
    1.94 +	containing different changes, for the <quote>1.0</quote>
    1.95 +	release.</para>
    1.96 +
    1.97 +      <para id="x_db">Given this, you can imagine that the consequences could be
    1.98 +	messy if you had a local <quote>0.9</quote> repository, and
    1.99 +	accidentally pulled changes from the shared <quote>1.0</quote>
   1.100 +	repository into it.  At worst, you could be paying
   1.101 +	insufficient attention, and push those changes into the shared
   1.102 +	<quote>0.9</quote> tree, confusing your entire team (but don't
   1.103 +	worry, we'll return to this horror scenario later).  However,
   1.104 +	it's more likely that you'll notice immediately, because
   1.105 +	Mercurial will display the URL it's pulling from, or you will
   1.106 +	see it pull a suspiciously large number of changes into the
   1.107 +	repository.</para>
   1.108 +
   1.109 +      <para id="x_dc">The <command role="hg-cmd">hg rollback</command> command
   1.110 +	will work nicely to expunge all of the changesets that you
   1.111 +	just pulled.  Mercurial groups all changes from one <command
   1.112 +	  role="hg-cmd">hg pull</command> into a single transaction,
   1.113 +	so one <command role="hg-cmd">hg rollback</command> is all you
   1.114 +	need to undo this mistake.</para>
   1.115 +
   1.116 +    </sect2>
   1.117 +    <sect2 id="sec:undo:rollback-after-push">
   1.118 +      <title>Rolling back is useless once you've pushed</title>
   1.119 +
   1.120 +      <para id="x_dd">The value of the <command role="hg-cmd">hg
   1.121 +	  rollback</command> command drops to zero once you've pushed
   1.122 +	your changes to another repository.  Rolling back a change
   1.123 +	makes it disappear entirely, but <emphasis>only</emphasis> in
   1.124 +	the repository in which you perform the <command
   1.125 +	  role="hg-cmd">hg rollback</command>.  Because a rollback
   1.126 +	eliminates history, there's no way for the disappearance of a
   1.127 +	change to propagate between repositories.</para>
   1.128 +
   1.129 +      <para id="x_de">If you've pushed a change to another
   1.130 +	repository&emdash;particularly if it's a shared
   1.131 +	repository&emdash;it has essentially <quote>escaped into the
   1.132 +	  wild,</quote> and you'll have to recover from your mistake
   1.133 +	in a different way.  If you push a changeset somewhere, then
   1.134 +	roll it back, then pull from the repository you pushed to, the
   1.135 +	changeset you thought you'd gotten rid of will simply reappear
   1.136 +	in your repository.</para>
   1.137 +
   1.138 +      <para id="x_df">(If you absolutely know for sure that the change
   1.139 +	you want to roll back is the most recent change in the
   1.140 +	repository that you pushed to, <emphasis>and</emphasis> you
   1.141 +	know that nobody else could have pulled it from that
   1.142 +	repository, you can roll back the changeset there, too, but
   1.143 +	you really should not expect this to work reliably.  Sooner or
   1.144 +	later a change really will make it into a repository that you
   1.145 +	don't directly control (or have forgotten about), and come
   1.146 +	back to bite you.)</para>
   1.147 +
   1.148 +    </sect2>
   1.149 +    <sect2>
   1.150 +      <title>You can only roll back once</title>
   1.151 +
   1.152 +      <para id="x_e0">Mercurial stores exactly one transaction in its
   1.153 +	transaction log; that transaction is the most recent one that
   1.154 +	occurred in the repository. This means that you can only roll
   1.155 +	back one transaction.  If you expect to be able to roll back
   1.156 +	one transaction, then its predecessor, this is not the
   1.157 +	behavior you will get.</para>
   1.158 +
   1.159 +      &interaction.rollback.twice;
   1.160 +
   1.161 +      <para id="x_e1">Once you've rolled back one transaction in a repository,
   1.162 +	you can't roll back again in that repository until you perform
   1.163 +	another commit or pull.</para>
   1.164 +
   1.165 +    </sect2>
   1.166 +  </sect1>
   1.167 +  <sect1>
   1.168 +    <title>Reverting the mistaken change</title>
   1.169 +
   1.170 +    <para id="x_e2">If you make a modification to a file, and decide that you
   1.171 +      really didn't want to change the file at all, and you haven't
   1.172 +      yet committed your changes, the <command role="hg-cmd">hg
   1.173 +	revert</command> command is the one you'll need.  It looks at
   1.174 +      the changeset that's the parent of the working directory, and
   1.175 +      restores the contents of the file to their state as of that
   1.176 +      changeset. (That's a long-winded way of saying that, in the
   1.177 +      normal case, it undoes your modifications.)</para>
   1.178 +
   1.179 +    <para id="x_e3">Let's illustrate how the <command role="hg-cmd">hg
   1.180 +	revert</command> command works with yet another small example.
   1.181 +      We'll begin by modifying a file that Mercurial is already
   1.182 +      tracking.</para>
   1.183 +
   1.184 +    &interaction.daily.revert.modify;
   1.185 +
   1.186 +    <para id="x_e4">If we don't
   1.187 +      want that change, we can simply <command role="hg-cmd">hg
   1.188 +	revert</command> the file.</para>
   1.189 +
   1.190 +      &interaction.daily.revert.unmodify;
   1.191 +
   1.192 +    <para id="x_e5">The <command role="hg-cmd">hg revert</command> command
   1.193 +      provides us with an extra degree of safety by saving our
   1.194 +      modified file with a <filename>.orig</filename>
   1.195 +      extension.</para>
   1.196 +
   1.197 +    &interaction.daily.revert.status;
   1.198 +
   1.199 +    <tip>
   1.200 +      <title>Be careful with <filename>.orig</filename> files</title>
   1.201 +
   1.202 +      <para id="x_6b8">It's extremely unlikely that you are either using
   1.203 +	Mercurial to manage files with <filename>.orig</filename>
   1.204 +	extensions or that you even care about the contents of such
   1.205 +	files.  Just in case, though, it's useful to remember that
   1.206 +	<command role="hg-cmd">hg revert</command> will
   1.207 +	unconditionally overwrite an existing file with a
   1.208 +	<filename>.orig</filename> extension. For instance, if you
   1.209 +	already have a file named <filename>foo.orig</filename> when
   1.210 +	you revert <filename>foo</filename>, the contents of
   1.211 +	<filename>foo.orig</filename> will be clobbered.</para>
   1.212 +    </tip>
   1.213 +
   1.214 +    <para id="x_e6">Here is a summary of the cases that the <command
   1.215 +	role="hg-cmd">hg revert</command> command can deal with.  We
   1.216 +      will describe each of these in more detail in the section that
   1.217 +      follows.</para>
   1.218 +    <itemizedlist>
   1.219 +      <listitem><para id="x_e7">If you modify a file, it will restore the file
   1.220 +	  to its unmodified state.</para>
   1.221 +      </listitem>
   1.222 +      <listitem><para id="x_e8">If you <command role="hg-cmd">hg add</command> a
   1.223 +	  file, it will undo the <quote>added</quote> state of the
   1.224 +	  file, but leave the file itself untouched.</para>
   1.225 +      </listitem>
   1.226 +      <listitem><para id="x_e9">If you delete a file without telling Mercurial,
   1.227 +	  it will restore the file to its unmodified contents.</para>
   1.228 +      </listitem>
   1.229 +      <listitem><para id="x_ea">If you use the <command role="hg-cmd">hg
   1.230 +	    remove</command> command to remove a file, it will undo
   1.231 +	  the <quote>removed</quote> state of the file, and restore
   1.232 +	  the file to its unmodified contents.</para>
   1.233 +      </listitem></itemizedlist>
   1.234 +
   1.235 +    <sect2 id="sec:undo:mgmt">
   1.236 +      <title>File management errors</title>
   1.237 +
   1.238 +      <para id="x_eb">The <command role="hg-cmd">hg revert</command> command is
   1.239 +	useful for more than just modified files.  It lets you reverse
   1.240 +	the results of all of Mercurial's file management
   1.241 +	commands&emdash;<command role="hg-cmd">hg add</command>,
   1.242 +	<command role="hg-cmd">hg remove</command>, and so on.</para>
   1.243 +
   1.244 +      <para id="x_ec">If you <command role="hg-cmd">hg add</command> a file,
   1.245 +	then decide that in fact you don't want Mercurial to track it,
   1.246 +	use <command role="hg-cmd">hg revert</command> to undo the
   1.247 +	add.  Don't worry; Mercurial will not modify the file in any
   1.248 +	way.  It will just <quote>unmark</quote> the file.</para>
   1.249 +
   1.250 +      &interaction.daily.revert.add;
   1.251 +
   1.252 +      <para id="x_ed">Similarly, if you ask Mercurial to <command
   1.253 +	  role="hg-cmd">hg remove</command> a file, you can use
   1.254 +	<command role="hg-cmd">hg revert</command> to restore it to
   1.255 +	the contents it had as of the parent of the working directory.
   1.256 +	&interaction.daily.revert.remove; This works just as
   1.257 +	well for a file that you deleted by hand, without telling
   1.258 +	Mercurial (recall that in Mercurial terminology, this kind of
   1.259 +	file is called <quote>missing</quote>).</para>
   1.260 +
   1.261 +      &interaction.daily.revert.missing;
   1.262 +
   1.263 +      <para id="x_ee">If you revert a <command role="hg-cmd">hg copy</command>,
   1.264 +	the copied-to file remains in your working directory
   1.265 +	afterwards, untracked.  Since a copy doesn't affect the
   1.266 +	copied-from file in any way, Mercurial doesn't do anything
   1.267 +	with the copied-from file.</para>
   1.268 +
   1.269 +      &interaction.daily.revert.copy;
   1.270 +    </sect2>
   1.271 +  </sect1>
   1.272 +
   1.273 +  <sect1>
   1.274 +    <title>Dealing with committed changes</title>
   1.275 +
   1.276 +    <para id="x_f5">Consider a case where you have committed a change
   1.277 +      <emphasis>a</emphasis>, and another change
   1.278 +      <emphasis>b</emphasis> on top of it; you then realise that
   1.279 +      change <emphasis>a</emphasis> was incorrect.  Mercurial lets you
   1.280 +      <quote>back out</quote> an entire changeset automatically, and
   1.281 +      building blocks that let you reverse part of a changeset by
   1.282 +      hand.</para>
   1.283 +
   1.284 +    <para id="x_f6">Before you read this section, here's something to
   1.285 +      keep in mind: the <command role="hg-cmd">hg backout</command>
   1.286 +      command undoes the effect of a change by
   1.287 +      <emphasis>adding</emphasis> to your repository's history, not by
   1.288 +      modifying or erasing it.  It's the right tool to use if you're
   1.289 +      fixing bugs, but not if you're trying to undo some change that
   1.290 +      has catastrophic consequences.  To deal with those, see
   1.291 +      <xref linkend="sec:undo:aaaiiieee"/>.</para>
   1.292 +
   1.293 +    <sect2>
   1.294 +      <title>Backing out a changeset</title>
   1.295 +
   1.296 +      <para id="x_f7">The <command role="hg-cmd">hg backout</command> command
   1.297 +	lets you <quote>undo</quote> the effects of an entire
   1.298 +	changeset in an automated fashion.  Because Mercurial's
   1.299 +	history is immutable, this command <emphasis>does
   1.300 +	  not</emphasis> get rid of the changeset you want to undo.
   1.301 +	Instead, it creates a new changeset that
   1.302 +	<emphasis>reverses</emphasis> the effect of the to-be-undone
   1.303 +	changeset.</para>
   1.304 +
   1.305 +      <para id="x_f8">The operation of the <command role="hg-cmd">hg
   1.306 +	  backout</command> command is a little intricate, so let's
   1.307 +	illustrate it with some examples.  First, we'll create a
   1.308 +	repository with some simple changes.</para>
   1.309 +
   1.310 +      &interaction.backout.init;
   1.311 +
   1.312 +      <para id="x_f9">The <command role="hg-cmd">hg backout</command> command
   1.313 +	takes a single changeset ID as its argument; this is the
   1.314 +	changeset to back out.  Normally, <command role="hg-cmd">hg
   1.315 +	  backout</command> will drop you into a text editor to write
   1.316 +	a commit message, so you can record why you're backing the
   1.317 +	change out.  In this example, we provide a commit message on
   1.318 +	the command line using the <option
   1.319 +	  role="hg-opt-backout">-m</option> option.</para>
   1.320 +
   1.321 +    </sect2>
   1.322 +    <sect2>
   1.323 +      <title>Backing out the tip changeset</title>
   1.324 +
   1.325 +      <para id="x_fa">We're going to start by backing out the last changeset we
   1.326 +	committed.</para>
   1.327 +
   1.328 +      &interaction.backout.simple;
   1.329 +
   1.330 +      <para id="x_fb">You can see that the second line from
   1.331 +	<filename>myfile</filename> is no longer present.  Taking a
   1.332 +	look at the output of <command role="hg-cmd">hg log</command>
   1.333 +	gives us an idea of what the <command role="hg-cmd">hg
   1.334 +	  backout</command> command has done.
   1.335 +	&interaction.backout.simple.log; Notice that the new changeset
   1.336 +	that <command role="hg-cmd">hg backout</command> has created
   1.337 +	is a child of the changeset we backed out.  It's easier to see
   1.338 +	this in <xref linkend="fig:undo:backout"/>, which presents a
   1.339 +	graphical view of the change history.  As you can see, the
   1.340 +	history is nice and linear.</para>
   1.341 +
   1.342 +      <figure id="fig:undo:backout">
   1.343 +	<title>Backing out a change using the <command
   1.344 +	    role="hg-cmd">hg backout</command> command</title>
   1.345 +	<mediaobject>
   1.346 +	  <imageobject><imagedata fileref="figs/undo-simple.png"/></imageobject>
   1.347 +	  <textobject><phrase>XXX add text</phrase></textobject>
   1.348 +	</mediaobject>
   1.349 +      </figure>
   1.350 +
   1.351 +    </sect2>
   1.352 +    <sect2>
   1.353 +      <title>Backing out a non-tip change</title>
   1.354 +
   1.355 +      <para id="x_fd">If you want to back out a change other than the last one
   1.356 +	you committed, pass the <option
   1.357 +	  role="hg-opt-backout">--merge</option> option to the
   1.358 +	<command role="hg-cmd">hg backout</command> command.</para>
   1.359 +
   1.360 +      &interaction.backout.non-tip.clone;
   1.361 +
   1.362 +      <para id="x_fe">This makes backing out any changeset a
   1.363 +	<quote>one-shot</quote> operation that's usually simple and
   1.364 +	fast.</para>
   1.365 +
   1.366 +      &interaction.backout.non-tip.backout;
   1.367 +
   1.368 +      <para id="x_ff">If you take a look at the contents of
   1.369 +	<filename>myfile</filename> after the backout finishes, you'll
   1.370 +	see that the first and third changes are present, but not the
   1.371 +	second.</para>
   1.372 +
   1.373 +      &interaction.backout.non-tip.cat;
   1.374 +
   1.375 +      <para id="x_100">As the graphical history in <xref
   1.376 +	  linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial
   1.377 +	still commits one change in this kind of situation (the
   1.378 +	box-shaped node is the ones that Mercurial commits
   1.379 +	automatically), but the revision graph now looks different.
   1.380 +	Before Mercurial begins the backout process, it first
   1.381 +	remembers what the current parent of the working directory is.
   1.382 +	It then backs out the target changeset, and commits that as a
   1.383 +	changeset.  Finally, it merges back to the previous parent of
   1.384 +	the working directory, but notice that it <emphasis>does not
   1.385 +	  commit</emphasis> the result of the merge.  The repository
   1.386 +	now contains two heads, and the working directory is in a
   1.387 +	merge state.</para>
   1.388 +
   1.389 +      <figure id="fig:undo:backout-non-tip">
   1.390 +	<title>Automated backout of a non-tip change using the
   1.391 +	  <command role="hg-cmd">hg backout</command> command</title>
   1.392 +	<mediaobject>
   1.393 +	  <imageobject><imagedata fileref="figs/undo-non-tip.png"/></imageobject>
   1.394 +	  <textobject><phrase>XXX add text</phrase></textobject>
   1.395 +	</mediaobject>
   1.396 +      </figure>
   1.397 +
   1.398 +      <para id="x_103">The result is that you end up <quote>back where you
   1.399 +	  were</quote>, only with some extra history that undoes the
   1.400 +	effect of the changeset you wanted to back out.</para>
   1.401 +
   1.402 +      <para id="x_6b9">You might wonder why Mercurial does not commit the result
   1.403 +	of the merge that it performed.  The reason lies in Mercurial
   1.404 +	behaving conservatively: a merge naturally has more scope for
   1.405 +	error than simply undoing the effect of the tip changeset,
   1.406 +	so your work will be safest if you first inspect (and test!)
   1.407 +	the result of the merge, <emphasis>then</emphasis> commit
   1.408 +	it.</para>
   1.409 +
   1.410 +      <sect3>
   1.411 +	<title>Always use the <option
   1.412 +	    role="hg-opt-backout">--merge</option> option</title>
   1.413 +
   1.414 +	<para id="x_104">In fact, since the <option
   1.415 +	    role="hg-opt-backout">--merge</option> option will do the
   1.416 +	  <quote>right thing</quote> whether or not the changeset
   1.417 +	  you're backing out is the tip (i.e. it won't try to merge if
   1.418 +	  it's backing out the tip, since there's no need), you should
   1.419 +	  <emphasis>always</emphasis> use this option when you run the
   1.420 +	  <command role="hg-cmd">hg backout</command> command.</para>
   1.421 +
   1.422 +      </sect3>
   1.423 +    </sect2>
   1.424 +    <sect2>
   1.425 +      <title>Gaining more control of the backout process</title>
   1.426 +
   1.427 +      <para id="x_105">While I've recommended that you always use the <option
   1.428 +	  role="hg-opt-backout">--merge</option> option when backing
   1.429 +	out a change, the <command role="hg-cmd">hg backout</command>
   1.430 +	command lets you decide how to merge a backout changeset.
   1.431 +	Taking control of the backout process by hand is something you
   1.432 +	will rarely need to do, but it can be useful to understand
   1.433 +	what the <command role="hg-cmd">hg backout</command> command
   1.434 +	is doing for you automatically.  To illustrate this, let's
   1.435 +	clone our first repository, but omit the backout change that
   1.436 +	it contains.</para>
   1.437 +
   1.438 +      &interaction.backout.manual.clone;
   1.439 +
   1.440 +      <para id="x_106">As with our
   1.441 +	earlier example, We'll commit a third changeset, then back out
   1.442 +	its parent, and see what happens.</para>
   1.443 +
   1.444 +      &interaction.backout.manual.backout;
   1.445 +
   1.446 +      <para id="x_107">Our new changeset is again a descendant of the changeset
   1.447 +	we backout out; it's thus a new head, <emphasis>not</emphasis>
   1.448 +	a descendant of the changeset that was the tip.  The <command
   1.449 +	  role="hg-cmd">hg backout</command> command was quite
   1.450 +	explicit in telling us this.</para>
   1.451 +
   1.452 +      &interaction.backout.manual.log;
   1.453 +
   1.454 +      <para id="x_108">Again, it's easier to see what has happened by looking at
   1.455 +	a graph of the revision history, in <xref
   1.456 +	  linkend="fig:undo:backout-manual"/>.  This makes it clear
   1.457 +	that when we use <command role="hg-cmd">hg backout</command>
   1.458 +	to back out a change other than the tip, Mercurial adds a new
   1.459 +	head to the repository (the change it committed is
   1.460 +	box-shaped).</para>
   1.461 +
   1.462 +      <figure id="fig:undo:backout-manual">
   1.463 +	<title>Backing out a change using the <command
   1.464 +	    role="hg-cmd">hg backout</command> command</title>
   1.465 +	<mediaobject>
   1.466 +	  <imageobject><imagedata fileref="figs/undo-manual.png"/></imageobject>
   1.467 +	  <textobject><phrase>XXX add text</phrase></textobject>
   1.468 +	</mediaobject>
   1.469 +      </figure>
   1.470 +
   1.471 +      <para id="x_10a">After the <command role="hg-cmd">hg backout</command>
   1.472 +	command has completed, it leaves the new
   1.473 +	<quote>backout</quote> changeset as the parent of the working
   1.474 +	directory.</para>
   1.475 +
   1.476 +      &interaction.backout.manual.parents;
   1.477 +
   1.478 +      <para id="x_10b">Now we have two isolated sets of changes.</para>
   1.479 +
   1.480 +      &interaction.backout.manual.heads;
   1.481 +
   1.482 +      <para id="x_10c">Let's think about what we expect to see as the contents of
   1.483 +	<filename>myfile</filename> now.  The first change should be
   1.484 +	present, because we've never backed it out.  The second change
   1.485 +	should be missing, as that's the change we backed out.  Since
   1.486 +	the history graph shows the third change as a separate head,
   1.487 +	we <emphasis>don't</emphasis> expect to see the third change
   1.488 +	present in <filename>myfile</filename>.</para>
   1.489 +
   1.490 +      &interaction.backout.manual.cat;
   1.491 +
   1.492 +      <para id="x_10d">To get the third change back into the file, we just do a
   1.493 +	normal merge of our two heads.</para>
   1.494 +
   1.495 +      &interaction.backout.manual.merge;
   1.496 +
   1.497 +      <para id="x_10e">Afterwards, the graphical history of our
   1.498 +	repository looks like
   1.499 +	<xref linkend="fig:undo:backout-manual-merge"/>.</para>
   1.500 +
   1.501 +      <figure id="fig:undo:backout-manual-merge">
   1.502 +	<title>Manually merging a backout change</title>
   1.503 +	<mediaobject>
   1.504 +	  <imageobject><imagedata fileref="figs/undo-manual-merge.png"/></imageobject>
   1.505 +	  <textobject><phrase>XXX add text</phrase></textobject>
   1.506 +	</mediaobject>
   1.507 +      </figure>
   1.508 +
   1.509 +    </sect2>
   1.510 +    <sect2>
   1.511 +      <title>Why <command role="hg-cmd">hg backout</command> works as
   1.512 +	it does</title>
   1.513 +
   1.514 +      <para id="x_110">Here's a brief description of how the <command
   1.515 +	  role="hg-cmd">hg backout</command> command works.</para>
   1.516 +      <orderedlist>
   1.517 +	<listitem><para id="x_111">It ensures that the working directory is
   1.518 +	    <quote>clean</quote>, i.e. that the output of <command
   1.519 +	      role="hg-cmd">hg status</command> would be empty.</para>
   1.520 +	</listitem>
   1.521 +	<listitem><para id="x_112">It remembers the current parent of the working
   1.522 +	    directory.  Let's call this changeset
   1.523 +	    <literal>orig</literal>.</para>
   1.524 +	</listitem>
   1.525 +	<listitem><para id="x_113">It does the equivalent of a <command
   1.526 +	      role="hg-cmd">hg update</command> to sync the working
   1.527 +	    directory to the changeset you want to back out.  Let's
   1.528 +	    call this changeset <literal>backout</literal>.</para>
   1.529 +	</listitem>
   1.530 +	<listitem><para id="x_114">It finds the parent of that changeset.  Let's
   1.531 +	    call that changeset <literal>parent</literal>.</para>
   1.532 +	</listitem>
   1.533 +	<listitem><para id="x_115">For each file that the
   1.534 +	    <literal>backout</literal> changeset affected, it does the
   1.535 +	    equivalent of a <command role="hg-cmd">hg revert -r
   1.536 +	      parent</command> on that file, to restore it to the
   1.537 +	    contents it had before that changeset was
   1.538 +	    committed.</para>
   1.539 +	</listitem>
   1.540 +	<listitem><para id="x_116">It commits the result as a new changeset.
   1.541 +	    This changeset has <literal>backout</literal> as its
   1.542 +	    parent.</para>
   1.543 +	</listitem>
   1.544 +	<listitem><para id="x_117">If you specify <option
   1.545 +	      role="hg-opt-backout">--merge</option> on the command
   1.546 +	    line, it merges with <literal>orig</literal>, and commits
   1.547 +	    the result of the merge.</para>
   1.548 +	</listitem></orderedlist>
   1.549 +
   1.550 +      <para id="x_118">An alternative way to implement the <command
   1.551 +	  role="hg-cmd">hg backout</command> command would be to
   1.552 +	<command role="hg-cmd">hg export</command> the
   1.553 +	to-be-backed-out changeset as a diff, then use the <option
   1.554 +	  role="cmd-opt-patch">--reverse</option> option to the
   1.555 +	<command>patch</command> command to reverse the effect of the
   1.556 +	change without fiddling with the working directory.  This
   1.557 +	sounds much simpler, but it would not work nearly as
   1.558 +	well.</para>
   1.559 +
   1.560 +      <para id="x_119">The reason that <command role="hg-cmd">hg
   1.561 +	  backout</command> does an update, a commit, a merge, and
   1.562 +	another commit is to give the merge machinery the best chance
   1.563 +	to do a good job when dealing with all the changes
   1.564 +	<emphasis>between</emphasis> the change you're backing out and
   1.565 +	the current tip.</para>
   1.566 +
   1.567 +      <para id="x_11a">If you're backing out a changeset that's 100 revisions
   1.568 +	back in your project's history, the chances that the
   1.569 +	<command>patch</command> command will be able to apply a
   1.570 +	reverse diff cleanly are not good, because intervening changes
   1.571 +	are likely to have <quote>broken the context</quote> that
   1.572 +	<command>patch</command> uses to determine whether it can
   1.573 +	apply a patch (if this sounds like gibberish, see <xref
   1.574 +	  linkend="sec:mq:patch"/> for a
   1.575 +	discussion of the <command>patch</command> command).  Also,
   1.576 +	Mercurial's merge machinery will handle files and directories
   1.577 +	being renamed, permission changes, and modifications to binary
   1.578 +	files, none of which <command>patch</command> can deal
   1.579 +	with.</para>
   1.580 +
   1.581 +    </sect2>
   1.582 +  </sect1>
   1.583 +  <sect1 id="sec:undo:aaaiiieee">
   1.584 +    <title>Changes that should never have been</title>
   1.585 +
   1.586 +    <para id="x_11b">Most of the time, the <command role="hg-cmd">hg
   1.587 +	backout</command> command is exactly what you need if you want
   1.588 +      to undo the effects of a change.  It leaves a permanent record
   1.589 +      of exactly what you did, both when committing the original
   1.590 +      changeset and when you cleaned up after it.</para>
   1.591 +
   1.592 +    <para id="x_11c">On rare occasions, though, you may find that you've
   1.593 +      committed a change that really should not be present in the
   1.594 +      repository at all.  For example, it would be very unusual, and
   1.595 +      usually considered a mistake, to commit a software project's
   1.596 +      object files as well as its source files.  Object files have
   1.597 +      almost no intrinsic value, and they're <emphasis>big</emphasis>,
   1.598 +      so they increase the size of the repository and the amount of
   1.599 +      time it takes to clone or pull changes.</para>
   1.600 +
   1.601 +    <para id="x_11d">Before I discuss the options that you have if you commit a
   1.602 +      <quote>brown paper bag</quote> change (the kind that's so bad
   1.603 +      that you want to pull a brown paper bag over your head), let me
   1.604 +      first discuss some approaches that probably won't work.</para>
   1.605 +
   1.606 +    <para id="x_11e">Since Mercurial treats history as
   1.607 +      accumulative&emdash;every change builds on top of all changes
   1.608 +      that preceded it&emdash;you generally can't just make disastrous
   1.609 +      changes disappear.  The one exception is when you've just
   1.610 +      committed a change, and it hasn't been pushed or pulled into
   1.611 +      another repository.  That's when you can safely use the <command
   1.612 +	role="hg-cmd">hg rollback</command> command, as I detailed in
   1.613 +      <xref linkend="sec:undo:rollback"/>.</para>
   1.614 +
   1.615 +    <para id="x_11f">After you've pushed a bad change to another repository, you
   1.616 +      <emphasis>could</emphasis> still use <command role="hg-cmd">hg
   1.617 +	rollback</command> to make your local copy of the change
   1.618 +      disappear, but it won't have the consequences you want.  The
   1.619 +      change will still be present in the remote repository, so it
   1.620 +      will reappear in your local repository the next time you
   1.621 +      pull.</para>
   1.622 +
   1.623 +    <para id="x_120">If a situation like this arises, and you know which
   1.624 +      repositories your bad change has propagated into, you can
   1.625 +      <emphasis>try</emphasis> to get rid of the change from
   1.626 +      <emphasis>every</emphasis> one of those repositories.  This is,
   1.627 +      of course, not a satisfactory solution: if you miss even a
   1.628 +      single repository while you're expunging, the change is still
   1.629 +      <quote>in the wild</quote>, and could propagate further.</para>
   1.630 +
   1.631 +    <para id="x_121">If you've committed one or more changes
   1.632 +      <emphasis>after</emphasis> the change that you'd like to see
   1.633 +      disappear, your options are further reduced. Mercurial doesn't
   1.634 +      provide a way to <quote>punch a hole</quote> in history, leaving
   1.635 +      changesets intact.</para>
   1.636 +
   1.637 +    <sect2>
   1.638 +      <title>Backing out a merge</title>
   1.639 +
   1.640 +      <para id="x_6ba">Since merges are often complicated, it is not unheard of
   1.641 +	for a merge to be mangled badly, but committed erroneously.
   1.642 +	Mercurial provides an important safeguard against bad merges
   1.643 +	by refusing to commit unresolved files, but human ingenuity
   1.644 +	guarantees that it is still possible to mess a merge up and
   1.645 +	commit it.</para>
   1.646 +
   1.647 +      <para id="x_6bb">Given a bad merge that has been committed, usually the
   1.648 +	best way to approach it is to simply try to repair the damage
   1.649 +	by hand.  A complete disaster that cannot be easily fixed up
   1.650 +	by hand ought to be very rare, but the <command
   1.651 +	  role="hg-cmd">hg backout</command> command may help in
   1.652 +	making the cleanup easier. It offers a <option
   1.653 +	  role="hg-opt-backout">--parent</option> option, which lets
   1.654 +	you specify which parent to revert to when backing out a
   1.655 +	merge.</para>
   1.656 +
   1.657 +      <figure id="fig:undo:bad-merge-1">
   1.658 +	<title>A bad merge</title>
   1.659 +	<mediaobject>
   1.660 +	  <imageobject><imagedata fileref="figs/bad-merge-1.png"/></imageobject>
   1.661 +	  <textobject><phrase>XXX add text</phrase></textobject>
   1.662 +	</mediaobject>
   1.663 +      </figure>
   1.664 +
   1.665 +      <para id="x_6bc">Suppose we have a revision graph like that in <xref
   1.666 +	  linkend="fig:undo:bad-merge-1"/>.  What we'd like is to
   1.667 +	<emphasis>redo</emphasis> the merge of revisions 2 and
   1.668 +	3.</para>
   1.669 +
   1.670 +      <para id="x_6bd">One way to do so would be as follows.</para>
   1.671 +
   1.672 +      <orderedlist>
   1.673 +	<listitem>
   1.674 +	  <para id="x_6be">Call <command role="hg-cmd">hg backout --rev=4
   1.675 +	      --parent=2</command>.  This tells <command
   1.676 +	      role="hg-cmd">hg backout</command> to back out revision
   1.677 +	    4, which is the bad merge, and to when deciding which
   1.678 +	    revision to prefer, to choose parent 2, one of the parents
   1.679 +	    of the merge.  The effect can be seen in <xref
   1.680 +	      linkend="fig:undo:bad-merge-2"/>.</para>
   1.681 +	  <figure id="fig:undo:bad-merge-2">
   1.682 +	    <title>Backing out the merge, favoring one parent</title>
   1.683 +	    <mediaobject>
   1.684 +	      <imageobject><imagedata fileref="figs/bad-merge-2.png"/></imageobject>
   1.685 +	      <textobject><phrase>XXX add text</phrase></textobject>
   1.686 +	    </mediaobject>
   1.687 +	  </figure>
   1.688 +	</listitem>
   1.689 +
   1.690 +	<listitem>
   1.691 +	  <para id="x_6bf">Call <command role="hg-cmd">hg backout --rev=4
   1.692 +	      --parent=3</command>.  This tells <command
   1.693 +	      role="hg-cmd">hg backout</command> to back out revision
   1.694 +	    4 again, but this time to choose parent 3, the other
   1.695 +	    parent of the merge.  The result is visible in <xref
   1.696 +	    linkend="fig:undo:bad-merge-3"/>, in which the repository
   1.697 +	    now contains three heads.</para>
   1.698 +	  <figure id="fig:undo:bad-merge-3">
   1.699 +	    <title>Backing out the merge, favoring the other
   1.700 +	      parent</title>
   1.701 +	    <mediaobject>
   1.702 +	      <imageobject><imagedata fileref="figs/bad-merge-3.png"/></imageobject>
   1.703 +	      <textobject><phrase>XXX add text</phrase></textobject>
   1.704 +	    </mediaobject>
   1.705 +	  </figure>
   1.706 +	</listitem>
   1.707 +
   1.708 +	<listitem>
   1.709 +	  <para id="x_6c0">Redo the bad merge by merging the two backout heads,
   1.710 +	    which reduces the number of heads in the repository to
   1.711 +	    two, as can be seen in <xref
   1.712 +	      linkend="fig:undo:bad-merge-4"/>.</para>
   1.713 +	  <figure id="fig:undo:bad-merge-4">
   1.714 +	    <title>Merging the backouts</title>
   1.715 +	    <mediaobject>
   1.716 +	      <imageobject><imagedata fileref="figs/bad-merge-4.png"/></imageobject>
   1.717 +	      <textobject><phrase>XXX add text</phrase></textobject>
   1.718 +	    </mediaobject>
   1.719 +	  </figure>
   1.720 +	</listitem>
   1.721 +
   1.722 +	<listitem>
   1.723 +	  <para id="x_6c1">Merge with the commit that was made after the bad
   1.724 +	    merge, as shown in <xref
   1.725 +	      linkend="fig:undo:bad-merge-5"/>.</para>
   1.726 +	  <figure id="fig:undo:bad-merge-5">
   1.727 +	    <title>Merging the backouts</title>
   1.728 +	    <mediaobject>
   1.729 +	      <imageobject><imagedata fileref="figs/bad-merge-5.png"/></imageobject>
   1.730 +	      <textobject><phrase>XXX add text</phrase></textobject>
   1.731 +	    </mediaobject>
   1.732 +	  </figure>
   1.733 +	</listitem>
   1.734 +      </orderedlist>
   1.735 +    </sect2>
   1.736 +
   1.737 +    <sect2>
   1.738 +      <title>Protect yourself from <quote>escaped</quote>
   1.739 +	changes</title>
   1.740 +
   1.741 +      <para id="x_123">If you've committed some changes to your local repository
   1.742 +	and they've been pushed or pulled somewhere else, this isn't
   1.743 +	necessarily a disaster.  You can protect yourself ahead of
   1.744 +	time against some classes of bad changeset.  This is
   1.745 +	particularly easy if your team usually pulls changes from a
   1.746 +	central repository.</para>
   1.747 +
   1.748 +      <para id="x_124">By configuring some hooks on that repository to validate
   1.749 +	incoming changesets (see chapter <xref linkend="chap:hook"/>),
   1.750 +	you can
   1.751 +	automatically prevent some kinds of bad changeset from being
   1.752 +	pushed to the central repository at all.  With such a
   1.753 +	configuration in place, some kinds of bad changeset will
   1.754 +	naturally tend to <quote>die out</quote> because they can't
   1.755 +	propagate into the central repository.  Better yet, this
   1.756 +	happens without any need for explicit intervention.</para>
   1.757 +
   1.758 +      <para id="x_125">For instance, an incoming change hook that
   1.759 +	verifies that a changeset will actually compile can prevent
   1.760 +	people from inadvertently <quote>breaking the
   1.761 +	  build</quote>.</para>
   1.762 +    </sect2>
   1.763 +
   1.764 +    <sect2>
   1.765 +      <title>What to do about sensitive changes that escape</title>
   1.766 +
   1.767 +      <para id="x_6c2">Even a carefully run project can suffer an unfortunate
   1.768 +	event such as the committing and uncontrolled propagation of a
   1.769 +	file that contains important passwords.</para>
   1.770 +
   1.771 +      <para id="x_6c3">If something like this happens to you, and the information
   1.772 +	that gets accidentally propagated is truly sensitive, your
   1.773 +	first step should be to mitigate the effect of the leak
   1.774 +	without trying to control the leak itself. If you are not 100%
   1.775 +	certain that you know exactly who could have seen the changes,
   1.776 +	you should immediately change passwords, cancel credit cards,
   1.777 +	or find some other way to make sure that the information that
   1.778 +	has leaked is no longer useful.  In other words, assume that
   1.779 +	the change has propagated far and wide, and that there's
   1.780 +	nothing more you can do.</para>
   1.781 +
   1.782 +      <para id="x_6c4">You might hope that there would be mechanisms you could
   1.783 +	use to either figure out who has seen a change or to erase the
   1.784 +	change permanently everywhere, but there are good reasons why
   1.785 +	these are not possible.</para>
   1.786 +
   1.787 +      <para id="x_6c5">Mercurial does not provide an audit trail of who has
   1.788 +	pulled changes from a repository, because it is usually either
   1.789 +	impossible to record such information or trivial to spoof it.
   1.790 +	In a multi-user or networked environment, you should thus be
   1.791 +	extremely skeptical of yourself if you think that you have
   1.792 +	identified every place that a sensitive changeset has
   1.793 +	propagated to.  Don't forget that people can and will send
   1.794 +	bundles by email, have their backup software save data
   1.795 +	offsite, carry repositories on USB sticks, and find other
   1.796 +	completely innocent ways to confound your attempts to track
   1.797 +	down every copy of a problematic change.</para>
   1.798 +
   1.799 +      <para id="x_6c6">Mercurial also does not provide a way to make a file or
   1.800 +	changeset completely disappear from history, because there is
   1.801 +	no way to enforce its disappearance; someone could easily
   1.802 +	modify their copy of Mercurial to ignore such directives. In
   1.803 +	addition, even if Mercurial provided such a capability,
   1.804 +	someone who simply hadn't pulled a <quote>make this file
   1.805 +	  disappear</quote> changeset wouldn't be affected by it, nor
   1.806 +	would web crawlers visiting at the wrong time, disk backups,
   1.807 +	or other mechanisms.  Indeed, no distributed revision control
   1.808 +	system can make data reliably vanish. Providing the illusion
   1.809 +	of such control could easily give a false sense of security,
   1.810 +	and be worse than not providing it at all.</para>
   1.811 +    </sect2>
   1.812 +  </sect1>
   1.813 +
   1.814 +  <sect1 id="sec:undo:bisect">
   1.815 +    <title>Finding the source of a bug</title>
   1.816 +
   1.817 +    <para id="x_126">While it's all very well to be able to back out a changeset
   1.818 +      that introduced a bug, this requires that you know which
   1.819 +      changeset to back out.  Mercurial provides an invaluable
   1.820 +      command, called <command role="hg-cmd">hg bisect</command>, that
   1.821 +      helps you to automate this process and accomplish it very
   1.822 +      efficiently.</para>
   1.823 +
   1.824 +    <para id="x_127">The idea behind the <command role="hg-cmd">hg
   1.825 +	bisect</command> command is that a changeset has introduced
   1.826 +      some change of behavior that you can identify with a simple
   1.827 +      pass/fail test.  You don't know which piece of code introduced the
   1.828 +      change, but you know how to test for the presence of the bug.
   1.829 +      The <command role="hg-cmd">hg bisect</command> command uses your
   1.830 +      test to direct its search for the changeset that introduced the
   1.831 +      code that caused the bug.</para>
   1.832 +
   1.833 +    <para id="x_128">Here are a few scenarios to help you understand how you
   1.834 +      might apply this command.</para>
   1.835 +    <itemizedlist>
   1.836 +      <listitem><para id="x_129">The most recent version of your software has a
   1.837 +	  bug that you remember wasn't present a few weeks ago, but
   1.838 +	  you don't know when it was introduced.  Here, your binary
   1.839 +	  test checks for the presence of that bug.</para>
   1.840 +      </listitem>
   1.841 +      <listitem><para id="x_12a">You fixed a bug in a rush, and now it's time to
   1.842 +	  close the entry in your team's bug database.  The bug
   1.843 +	  database requires a changeset ID when you close an entry,
   1.844 +	  but you don't remember which changeset you fixed the bug in.
   1.845 +	  Once again, your binary test checks for the presence of the
   1.846 +	  bug.</para>
   1.847 +      </listitem>
   1.848 +      <listitem><para id="x_12b">Your software works correctly, but runs 15%
   1.849 +	  slower than the last time you measured it.  You want to know
   1.850 +	  which changeset introduced the performance regression.  In
   1.851 +	  this case, your binary test measures the performance of your
   1.852 +	  software, to see whether it's <quote>fast</quote> or
   1.853 +	  <quote>slow</quote>.</para>
   1.854 +      </listitem>
   1.855 +      <listitem><para id="x_12c">The sizes of the components of your project that
   1.856 +	  you ship exploded recently, and you suspect that something
   1.857 +	  changed in the way you build your project.</para>
   1.858 +      </listitem></itemizedlist>
   1.859 +
   1.860 +    <para id="x_12d">From these examples, it should be clear that the <command
   1.861 +	role="hg-cmd">hg bisect</command> command is not useful only
   1.862 +      for finding the sources of bugs.  You can use it to find any
   1.863 +      <quote>emergent property</quote> of a repository (anything that
   1.864 +      you can't find from a simple text search of the files in the
   1.865 +      tree) for which you can write a binary test.</para>
   1.866 +
   1.867 +    <para id="x_12e">We'll introduce a little bit of terminology here, just to
   1.868 +      make it clear which parts of the search process are your
   1.869 +      responsibility, and which are Mercurial's.  A
   1.870 +      <emphasis>test</emphasis> is something that
   1.871 +      <emphasis>you</emphasis> run when <command role="hg-cmd">hg
   1.872 +	bisect</command> chooses a changeset.  A
   1.873 +      <emphasis>probe</emphasis> is what <command role="hg-cmd">hg
   1.874 +	bisect</command> runs to tell whether a revision is good.
   1.875 +      Finally, we'll use the word <quote>bisect</quote>, as both a
   1.876 +      noun and a verb, to stand in for the phrase <quote>search using
   1.877 +	the <command role="hg-cmd">hg bisect</command>
   1.878 +	command</quote>.</para>
   1.879 +
   1.880 +    <para id="x_12f">One simple way to automate the searching process would be
   1.881 +      simply to probe every changeset.  However, this scales poorly.
   1.882 +      If it took ten minutes to test a single changeset, and you had
   1.883 +      10,000 changesets in your repository, the exhaustive approach
   1.884 +      would take on average 35 <emphasis>days</emphasis> to find the
   1.885 +      changeset that introduced a bug.  Even if you knew that the bug
   1.886 +      was introduced by one of the last 500 changesets, and limited
   1.887 +      your search to those, you'd still be looking at over 40 hours to
   1.888 +      find the changeset that introduced your bug.</para>
   1.889 +
   1.890 +    <para id="x_130">What the <command role="hg-cmd">hg bisect</command> command
   1.891 +      does is use its knowledge of the <quote>shape</quote> of your
   1.892 +      project's revision history to perform a search in time
   1.893 +      proportional to the <emphasis>logarithm</emphasis> of the number
   1.894 +      of changesets to check (the kind of search it performs is called
   1.895 +      a dichotomic search).  With this approach, searching through
   1.896 +      10,000 changesets will take less than three hours, even at ten
   1.897 +      minutes per test (the search will require about 14 tests).
   1.898 +      Limit your search to the last hundred changesets, and it will
   1.899 +      take only about an hour (roughly seven tests).</para>
   1.900 +
   1.901 +    <para id="x_131">The <command role="hg-cmd">hg bisect</command> command is
   1.902 +      aware of the <quote>branchy</quote> nature of a Mercurial
   1.903 +      project's revision history, so it has no problems dealing with
   1.904 +      branches, merges, or multiple heads in a repository.  It can
   1.905 +      prune entire branches of history with a single probe, which is
   1.906 +      how it operates so efficiently.</para>
   1.907 +
   1.908 +    <sect2>
   1.909 +      <title>Using the <command role="hg-cmd">hg bisect</command>
   1.910 +	command</title>
   1.911 +
   1.912 +      <para id="x_132">Here's an example of <command role="hg-cmd">hg
   1.913 +	  bisect</command> in action.</para>
   1.914 +
   1.915 +      <note>
   1.916 +	<para id="x_133">  In versions 0.9.5 and earlier of Mercurial, <command
   1.917 +	    role="hg-cmd">hg bisect</command> was not a core command:
   1.918 +	  it was distributed with Mercurial as an extension. This
   1.919 +	  section describes the built-in command, not the old
   1.920 +	  extension.</para>
   1.921 +      </note>
   1.922 +
   1.923 +      <para id="x_134">Now let's create a repository, so that we can try out the
   1.924 +	<command role="hg-cmd">hg bisect</command> command in
   1.925 +	isolation.</para>
   1.926 +
   1.927 +      &interaction.bisect.init;
   1.928 +
   1.929 +      <para id="x_135">We'll simulate a project that has a bug in it in a
   1.930 +	simple-minded way: create trivial changes in a loop, and
   1.931 +	nominate one specific change that will have the
   1.932 +	<quote>bug</quote>.  This loop creates 35 changesets, each
   1.933 +	adding a single file to the repository. We'll represent our
   1.934 +	<quote>bug</quote> with a file that contains the text <quote>i
   1.935 +	  have a gub</quote>.</para>
   1.936 +
   1.937 +      &interaction.bisect.commits;
   1.938 +
   1.939 +      <para id="x_136">The next thing that we'd like to do is figure out how to
   1.940 +	use the <command role="hg-cmd">hg bisect</command> command.
   1.941 +	We can use Mercurial's normal built-in help mechanism for
   1.942 +	this.</para>
   1.943 +
   1.944 +      &interaction.bisect.help;
   1.945 +
   1.946 +      <para id="x_137">The <command role="hg-cmd">hg bisect</command> command
   1.947 +	works in steps.  Each step proceeds as follows.</para>
   1.948 +      <orderedlist>
   1.949 +	<listitem><para id="x_138">You run your binary test.</para>
   1.950 +	  <itemizedlist>
   1.951 +	    <listitem><para id="x_139">If the test succeeded, you tell <command
   1.952 +		  role="hg-cmd">hg bisect</command> by running the
   1.953 +		<command role="hg-cmd">hg bisect --good</command>
   1.954 +		command.</para>
   1.955 +	    </listitem>
   1.956 +	    <listitem><para id="x_13a">If it failed, run the <command
   1.957 +		  role="hg-cmd">hg bisect --bad</command>
   1.958 +		command.</para></listitem></itemizedlist>
   1.959 +	</listitem>
   1.960 +	<listitem><para id="x_13b">The command uses your information to decide
   1.961 +	    which changeset to test next.</para>
   1.962 +	</listitem>
   1.963 +	<listitem><para id="x_13c">It updates the working directory to that
   1.964 +	    changeset, and the process begins again.</para>
   1.965 +	</listitem></orderedlist>
   1.966 +      <para id="x_13d">The process ends when <command role="hg-cmd">hg
   1.967 +	  bisect</command> identifies a unique changeset that marks
   1.968 +	the point where your test transitioned from
   1.969 +	<quote>succeeding</quote> to <quote>failing</quote>.</para>
   1.970 +
   1.971 +      <para id="x_13e">To start the search, we must run the <command
   1.972 +	  role="hg-cmd">hg bisect --reset</command> command.</para>
   1.973 +
   1.974 +      &interaction.bisect.search.init;
   1.975 +
   1.976 +      <para id="x_13f">In our case, the binary test we use is simple: we check to
   1.977 +	see if any file in the repository contains the string <quote>i
   1.978 +	  have a gub</quote>.  If it does, this changeset contains the
   1.979 +	change that <quote>caused the bug</quote>.  By convention, a
   1.980 +	changeset that has the property we're searching for is
   1.981 +	<quote>bad</quote>, while one that doesn't is
   1.982 +	<quote>good</quote>.</para>
   1.983 +
   1.984 +      <para id="x_140">Most of the time, the revision to which the working
   1.985 +	directory is synced (usually the tip) already exhibits the
   1.986 +	problem introduced by the buggy change, so we'll mark it as
   1.987 +	<quote>bad</quote>.</para>
   1.988 +
   1.989 +      &interaction.bisect.search.bad-init;
   1.990 +
   1.991 +      <para id="x_141">Our next task is to nominate a changeset that we know
   1.992 +	<emphasis>doesn't</emphasis> have the bug; the <command
   1.993 +	  role="hg-cmd">hg bisect</command> command will
   1.994 +	<quote>bracket</quote> its search between the first pair of
   1.995 +	good and bad changesets.  In our case, we know that revision
   1.996 +	10 didn't have the bug.  (I'll have more words about choosing
   1.997 +	the first <quote>good</quote> changeset later.)</para>
   1.998 +
   1.999 +      &interaction.bisect.search.good-init;
  1.1000 +
  1.1001 +      <para id="x_142">Notice that this command printed some output.</para>
  1.1002 +      <itemizedlist>
  1.1003 +	<listitem><para id="x_143">It told us how many changesets it must
  1.1004 +	    consider before it can identify the one that introduced
  1.1005 +	    the bug, and how many tests that will require.</para>
  1.1006 +	</listitem>
  1.1007 +	<listitem><para id="x_144">It updated the working directory to the next
  1.1008 +	    changeset to test, and told us which changeset it's
  1.1009 +	    testing.</para>
  1.1010 +	</listitem></itemizedlist>
  1.1011 +
  1.1012 +      <para id="x_145">We now run our test in the working directory.  We use the
  1.1013 +	<command>grep</command> command to see if our
  1.1014 +	<quote>bad</quote> file is present in the working directory.
  1.1015 +	If it is, this revision is bad; if not, this revision is good.
  1.1016 +	&interaction.bisect.search.step1;</para>
  1.1017 +
  1.1018 +      <para id="x_146">This test looks like a perfect candidate for automation,
  1.1019 +	so let's turn it into a shell function.</para>
  1.1020 +      &interaction.bisect.search.mytest;
  1.1021 +
  1.1022 +      <para id="x_147">We can now run an entire test step with a single command,
  1.1023 +	<literal>mytest</literal>.</para>
  1.1024 +
  1.1025 +      &interaction.bisect.search.step2;
  1.1026 +
  1.1027 +      <para id="x_148">A few more invocations of our canned test step command,
  1.1028 +	and we're done.</para>
  1.1029 +
  1.1030 +      &interaction.bisect.search.rest;
  1.1031 +
  1.1032 +      <para id="x_149">Even though we had 40 changesets to search through, the
  1.1033 +	<command role="hg-cmd">hg bisect</command> command let us find
  1.1034 +	the changeset that introduced our <quote>bug</quote> with only
  1.1035 +	five tests.  Because the number of tests that the <command
  1.1036 +	  role="hg-cmd">hg bisect</command> command performs grows
  1.1037 +	logarithmically with the number of changesets to search, the
  1.1038 +	advantage that it has over the <quote>brute force</quote>
  1.1039 +	search approach increases with every changeset you add.</para>
  1.1040 +
  1.1041 +    </sect2>
  1.1042 +    <sect2>
  1.1043 +      <title>Cleaning up after your search</title>
  1.1044 +
  1.1045 +      <para id="x_14a">When you're finished using the <command role="hg-cmd">hg
  1.1046 +	  bisect</command> command in a repository, you can use the
  1.1047 +	<command role="hg-cmd">hg bisect --reset</command> command to
  1.1048 +	drop the information it was using to drive your search.  The
  1.1049 +	command doesn't use much space, so it doesn't matter if you
  1.1050 +	forget to run this command.  However, <command
  1.1051 +	  role="hg-cmd">hg bisect</command> won't let you start a new
  1.1052 +	search in that repository until you do a <command
  1.1053 +	  role="hg-cmd">hg bisect --reset</command>.</para>
  1.1054 +
  1.1055 +      &interaction.bisect.search.reset;
  1.1056 +
  1.1057 +    </sect2>
  1.1058 +  </sect1>
  1.1059 +  <sect1>
  1.1060 +    <title>Tips for finding bugs effectively</title>
  1.1061 +
  1.1062 +    <sect2>
  1.1063 +      <title>Give consistent input</title>
  1.1064 +
  1.1065 +      <para id="x_14b">The <command role="hg-cmd">hg bisect</command> command
  1.1066 +	requires that you correctly report the result of every test
  1.1067 +	you perform.  If you tell it that a test failed when it really
  1.1068 +	succeeded, it <emphasis>might</emphasis> be able to detect the
  1.1069 +	inconsistency.  If it can identify an inconsistency in your
  1.1070 +	reports, it will tell you that a particular changeset is both
  1.1071 +	good and bad. However, it can't do this perfectly; it's about
  1.1072 +	as likely to report the wrong changeset as the source of the
  1.1073 +	bug.</para>
  1.1074 +
  1.1075 +    </sect2>
  1.1076 +    <sect2>
  1.1077 +      <title>Automate as much as possible</title>
  1.1078 +
  1.1079 +      <para id="x_14c">When I started using the <command role="hg-cmd">hg
  1.1080 +	  bisect</command> command, I tried a few times to run my
  1.1081 +	tests by hand, on the command line.  This is an approach that
  1.1082 +	I, at least, am not suited to.  After a few tries, I found
  1.1083 +	that I was making enough mistakes that I was having to restart
  1.1084 +	my searches several times before finally getting correct
  1.1085 +	results.</para>
  1.1086 +
  1.1087 +      <para id="x_14d">My initial problems with driving the <command
  1.1088 +	  role="hg-cmd">hg bisect</command> command by hand occurred
  1.1089 +	even with simple searches on small repositories; if the
  1.1090 +	problem you're looking for is more subtle, or the number of
  1.1091 +	tests that <command role="hg-cmd">hg bisect</command> must
  1.1092 +	perform increases, the likelihood of operator error ruining
  1.1093 +	the search is much higher.  Once I started automating my
  1.1094 +	tests, I had much better results.</para>
  1.1095 +
  1.1096 +      <para id="x_14e">The key to automated testing is twofold:</para>
  1.1097 +      <itemizedlist>
  1.1098 +	<listitem><para id="x_14f">always test for the same symptom, and</para>
  1.1099 +	</listitem>
  1.1100 +	<listitem><para id="x_150">always feed consistent input to the <command
  1.1101 +	      role="hg-cmd">hg bisect</command> command.</para>
  1.1102 +	</listitem></itemizedlist>
  1.1103 +      <para id="x_151">In my tutorial example above, the <command>grep</command>
  1.1104 +	command tests for the symptom, and the <literal>if</literal>
  1.1105 +	statement takes the result of this check and ensures that we
  1.1106 +	always feed the same input to the <command role="hg-cmd">hg
  1.1107 +	  bisect</command> command.  The <literal>mytest</literal>
  1.1108 +	function marries these together in a reproducible way, so that
  1.1109 +	every test is uniform and consistent.</para>
  1.1110 +
  1.1111 +    </sect2>
  1.1112 +    <sect2>
  1.1113 +      <title>Check your results</title>
  1.1114 +
  1.1115 +      <para id="x_152">Because the output of a <command role="hg-cmd">hg
  1.1116 +	  bisect</command> search is only as good as the input you
  1.1117 +	give it, don't take the changeset it reports as the absolute
  1.1118 +	truth.  A simple way to cross-check its report is to manually
  1.1119 +	run your test at each of the following changesets:</para>
  1.1120 +      <itemizedlist>
  1.1121 +	<listitem><para id="x_153">The changeset that it reports as the first bad
  1.1122 +	    revision.  Your test should still report this as
  1.1123 +	    bad.</para>
  1.1124 +	</listitem>
  1.1125 +	<listitem><para id="x_154">The parent of that changeset (either parent,
  1.1126 +	    if it's a merge). Your test should report this changeset
  1.1127 +	    as good.</para>
  1.1128 +	</listitem>
  1.1129 +	<listitem><para id="x_155">A child of that changeset.  Your test should
  1.1130 +	    report this changeset as bad.</para>
  1.1131 +	</listitem></itemizedlist>
  1.1132 +
  1.1133 +    </sect2>
  1.1134 +    <sect2>
  1.1135 +      <title>Beware interference between bugs</title>
  1.1136 +
  1.1137 +      <para id="x_156">It's possible that your search for one bug could be
  1.1138 +	disrupted by the presence of another.  For example, let's say
  1.1139 +	your software crashes at revision 100, and worked correctly at
  1.1140 +	revision 50.  Unknown to you, someone else introduced a
  1.1141 +	different crashing bug at revision 60, and fixed it at
  1.1142 +	revision 80.  This could distort your results in one of
  1.1143 +	several ways.</para>
  1.1144 +
  1.1145 +      <para id="x_157">It is possible that this other bug completely
  1.1146 +	<quote>masks</quote> yours, which is to say that it occurs
  1.1147 +	before your bug has a chance to manifest itself.  If you can't
  1.1148 +	avoid that other bug (for example, it prevents your project
  1.1149 +	from building), and so can't tell whether your bug is present
  1.1150 +	in a particular changeset, the <command role="hg-cmd">hg
  1.1151 +	  bisect</command> command cannot help you directly.  Instead,
  1.1152 +	you can mark a changeset as untested by running <command
  1.1153 +	  role="hg-cmd">hg bisect --skip</command>.</para>
  1.1154 +
  1.1155 +      <para id="x_158">A different problem could arise if your test for a bug's
  1.1156 +	presence is not specific enough.  If you check for <quote>my
  1.1157 +	  program crashes</quote>, then both your crashing bug and an
  1.1158 +	unrelated crashing bug that masks it will look like the same
  1.1159 +	thing, and mislead <command role="hg-cmd">hg
  1.1160 +	  bisect</command>.</para>
  1.1161 +
  1.1162 +      <para id="x_159">Another useful situation in which to use <command
  1.1163 +	  role="hg-cmd">hg bisect --skip</command> is if you can't
  1.1164 +	test a revision because your project was in a broken and hence
  1.1165 +	untestable state at that revision, perhaps because someone
  1.1166 +	checked in a change that prevented the project from
  1.1167 +	building.</para>
  1.1168 +
  1.1169 +    </sect2>
  1.1170 +    <sect2>
  1.1171 +      <title>Bracket your search lazily</title>
  1.1172 +
  1.1173 +      <para id="x_15a">Choosing the first <quote>good</quote> and
  1.1174 +	<quote>bad</quote> changesets that will mark the end points of
  1.1175 +	your search is often easy, but it bears a little discussion
  1.1176 +	nevertheless.  From the perspective of <command
  1.1177 +	  role="hg-cmd">hg bisect</command>, the <quote>newest</quote>
  1.1178 +	changeset is conventionally <quote>bad</quote>, and the older
  1.1179 +	changeset is <quote>good</quote>.</para>
  1.1180 +
  1.1181 +      <para id="x_15b">If you're having trouble remembering when a suitable
  1.1182 +	<quote>good</quote> change was, so that you can tell <command
  1.1183 +	  role="hg-cmd">hg bisect</command>, you could do worse than
  1.1184 +	testing changesets at random.  Just remember to eliminate
  1.1185 +	contenders that can't possibly exhibit the bug (perhaps
  1.1186 +	because the feature with the bug isn't present yet) and those
  1.1187 +	where another problem masks the bug (as I discussed
  1.1188 +	above).</para>
  1.1189 +
  1.1190 +      <para id="x_15c">Even if you end up <quote>early</quote> by thousands of
  1.1191 +	changesets or months of history, you will only add a handful
  1.1192 +	of tests to the total number that <command role="hg-cmd">hg
  1.1193 +	  bisect</command> must perform, thanks to its logarithmic
  1.1194 +	behavior.</para>
  1.1195 +
  1.1196 +    </sect2>
  1.1197 +  </sect1>
  1.1198 +</chapter>
  1.1199 +
  1.1200 +<!--
  1.1201 +local variables: 
  1.1202 +sgml-parent-document: ("00book.xml" "book" "chapter")
  1.1203 +end:
  1.1204 +-->