--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/html/backup/abcd.html Mon Jan 25 18:56:45 2010 +0530
@@ -0,0 +1,929 @@
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Chapter 9. Finding and fixing mistakes</title><link rel="stylesheet" href="/support/styles.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"><link rel="home" href="index.html" title="Mercurial: The Definitive Guide"><link rel="up" href="index.html" title="Mercurial: The Definitive Guide"><link rel="prev" href="managing-releases-and-branchy-development.html" title="Chapter 8. Managing releases and branchy development"><link rel="next" href="handling-repository-events-with-hooks.html" title="Chapter 10. Handling repository events with hooks"><link rel="alternate" type="application/atom+xml" title="Comments" href="/feeds/comments/"><link rel="shortcut icon" type="image/png" href="/support/figs/favicon.png"><script type="text/javascript" src="/support/jquery-min.js"></script><script type="text/javascript" src="/support/form.js"></script><script type="text/javascript" src="/support/hsbook.js"></script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><h2 class="booktitle"><a href="/">Mercurial: The Definitive Guide</a><span class="authors">by Bryan O'Sullivan</span></h2></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 9. Finding and fixing mistakes</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="managing-releases-and-branchy-development.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="handling-repository-events-with-hooks.html">Next</a></td></tr></table></div><div class="chapter" lang="en" id="chap:undo"><div class="titlepage"><div><div><h2 class="title">Chapter 9. Finding and fixing mistakes</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#id390081">Erasing local history</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id390087">The accidental commit</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#sec:undo:rollback">Rolling back a transaction</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id390858">The erroneous pull</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#sec:undo:rollback-after-push">Rolling back is useless once you've pushed</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id391000">You can only roll back once</a></span></dt></dl></dd><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#id391367">Reverting the mistaken change</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#sec:undo:mgmt">File management errors</a></span></dt></dl></dd><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#id392218">Dealing with committed changes</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id392287">Backing out a changeset</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id392424">Backing out the tip changeset</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id392766">Backing out a non-tip change</a></span></dt><dd><dl><dt><span class="sect3"><a href="finding-and-fixing-mistakes.html#id392990">Always use the --merge option</a></span></dt></dl></dd><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id393181">Gaining more control of the backout process</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id393814">Why hg backout works as
+ it does</a></span></dt></dl></dd><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#sec:undo:aaaiiieee">Changes that should never have been</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id394303">Backing out a merge</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id394612">Protect yourself from escaped
+ changes</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id394667">What to do about sensitive changes that escape</a></span></dt></dl></dd><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#sec:undo:bisect">Finding the source of a bug</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id394992">Using the hg bisect
+ command</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396541">Cleaning up after your search</a></span></dt></dl></dd><dt><span class="sect1"><a href="finding-and-fixing-mistakes.html#id396622">Tips for finding bugs effectively</a></span></dt><dd><dl><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396628">Give consistent input</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396884">Automate as much as possible</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396713">Check your results</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396770">Beware interference between bugs</a></span></dt><dt><span class="sect2"><a href="finding-and-fixing-mistakes.html#id396856">Bracket your search lazily</a></span></dt></dl></dd></dl></div><p id="x_d2"><a name="x_d2"></a>To err might be human, but to really handle the consequences
+ well takes a top-notch revision control system. In this chapter,
+ we'll discuss some of the techniques you can use when you find
+ that a problem has crept into your project. Mercurial has some
+ highly capable features that will help you to isolate the sources
+ of problems, and to handle them appropriately.</p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id390081">Erasing local history</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id390087">The accidental commit</h3></div></div></div><p id="x_d3"><a name="x_d3"></a>I have the occasional but persistent problem of typing
+ rather more quickly than I can think, which sometimes results
+ in me committing a changeset that is either incomplete or
+ plain wrong. In my case, the usual kind of incomplete
+ changeset is one in which I've created a new source file, but
+ forgotten to <span class="command"><strong>hg add</strong></span> it. A
+ “<span class="quote">plain wrong</span>” changeset is not as common, but no
+ less annoying.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="sec:undo:rollback">Rolling back a transaction</h3></div></div></div><p id="x_d4"><a name="x_d4"></a>In <a class="xref" href="behind-the-scenes.html#sec:concepts:txn" title="Safe operation">the section called “Safe operation”</a>, I
+ mentioned that Mercurial treats each modification of a
+ repository as a <span class="emphasis"><em>transaction</em></span>. Every time
+ you commit a changeset or pull changes from another
+ repository, Mercurial remembers what you did. You can undo,
+ or <span class="emphasis"><em>roll back</em></span>, exactly one of these
+ actions using the <span class="command"><strong>hg rollback</strong></span>
+
+ command. (See <a class="xref" href="finding-and-fixing-mistakes.html#sec:undo:rollback-after-push" title="Rolling back is useless once you've pushed">the section called “Rolling back is useless once you've pushed”</a>
+ for an important caveat about the use of this command.)</p><p id="x_d5"><a name="x_d5"></a>Here's a mistake that I often find myself making:
+ committing a change in which I've created a new file, but
+ forgotten to <span class="command"><strong>hg add</strong></span>
+ it.</p><pre id="id390839" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
+M a
+<code class="prompt">$</code> <strong class="userinput"><code>echo b > b</code></strong>
+
+<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Add file b'</code></strong>
+</pre><p id="x_d6"><a name="x_d6"></a>Looking at the output of <span class="command"><strong>hg
+ status</strong></span> after the commit immediately confirms the
+ error.</p><pre id="id390541" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
+? b
+<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
+
+changeset: 1:f2db1de2ba4f
+tag: tip
+user: Bryan O'Sullivan <bos@serpentine.com>
+date: Tue May 05 06:55:44 2009 +0000
+summary: Add file b
+
+</pre><p id="x_d7"><a name="x_d7"></a>The commit captured the changes to the file
+ <code class="filename">a</code>, but not the new file
+ <code class="filename">b</code>. If I were to push this changeset to a
+ repository that I shared with a colleague, the chances are
+ high that something in <code class="filename">a</code> would refer to
+ <code class="filename">b</code>, which would not be present in their
+ repository when they pulled my changes. I would thus become
+ the object of some indignation.</p><p id="x_d8"><a name="x_d8"></a>However, luck is with me—I've caught my error
+ before I pushed the changeset. I use the <span class="command"><strong>hg rollback</strong></span> command, and Mercurial
+ makes that last changeset vanish.</p><pre id="id391066" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg rollback</code></strong>
+
+rolling back last transaction
+<code class="prompt">$</code> <strong class="userinput"><code>hg tip</code></strong>
+changeset: 0:cde70bc943e1
+tag: tip
+user: Bryan O'Sullivan <bos@serpentine.com>
+date: Tue May 05 06:55:44 2009 +0000
+summary: First commit
+
+<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
+M a
+? b
+</pre><p id="x_d9"><a name="x_d9"></a>Notice that the changeset is no longer present in the
+ repository's history, and the working directory once again
+ thinks that the file <code class="filename">a</code> is modified. The
+ commit and rollback have left the working directory exactly as
+ it was prior to the commit; the changeset has been completely
+ erased. I can now safely <span class="command"><strong>hg
+ add</strong></span> the file <code class="filename">b</code>, and rerun my
+ commit.</p><pre id="id391024" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg add b</code></strong>
+
+<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'Add file b, this time for real'</code></strong>
+</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id390858">The erroneous pull</h3></div></div></div><p id="x_da"><a name="x_da"></a>It's common practice with Mercurial to maintain separate
+ development branches of a project in different repositories.
+ Your development team might have one shared repository for
+ your project's “<span class="quote">0.9</span>” release, and another,
+ containing different changes, for the “<span class="quote">1.0</span>”
+ release.</p><p id="x_db"><a name="x_db"></a>Given this, you can imagine that the consequences could be
+ messy if you had a local “<span class="quote">0.9</span>” repository, and
+ accidentally pulled changes from the shared “<span class="quote">1.0</span>”
+ repository into it. At worst, you could be paying
+ insufficient attention, and push those changes into the shared
+ “<span class="quote">0.9</span>” tree, confusing your entire team (but don't
+ worry, we'll return to this horror scenario later). However,
+ it's more likely that you'll notice immediately, because
+ Mercurial will display the URL it's pulling from, or you will
+ see it pull a suspiciously large number of changes into the
+ repository.</p><p id="x_dc"><a name="x_dc"></a>The <span class="command"><strong>hg rollback</strong></span> command
+ will work nicely to expunge all of the changesets that you
+ just pulled. Mercurial groups all changes from one <span class="command"><strong>hg pull</strong></span> into a single transaction,
+ so one <span class="command"><strong>hg rollback</strong></span> is all you
+ need to undo this mistake.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="sec:undo:rollback-after-push">Rolling back is useless once you've pushed</h3></div></div></div><p id="x_dd"><a name="x_dd"></a>The value of the <span class="command"><strong>hg
+ rollback</strong></span> command drops to zero once you've pushed
+ your changes to another repository. Rolling back a change
+ makes it disappear entirely, but <span class="emphasis"><em>only</em></span> in
+ the repository in which you perform the <span class="command"><strong>hg rollback</strong></span>. Because a rollback
+ eliminates history, there's no way for the disappearance of a
+ change to propagate between repositories.</p><p id="x_de"><a name="x_de"></a>If you've pushed a change to another
+ repository—particularly if it's a shared
+ repository—it has essentially “<span class="quote">escaped into the
+ wild,</span>” and you'll have to recover from your mistake
+ in a different way. If you push a changeset somewhere, then
+ roll it back, then pull from the repository you pushed to, the
+ changeset you thought you'd gotten rid of will simply reappear
+ in your repository.</p><p id="x_df"><a name="x_df"></a>(If you absolutely know for sure that the change
+ you want to roll back is the most recent change in the
+ repository that you pushed to, <span class="emphasis"><em>and</em></span> you
+ know that nobody else could have pulled it from that
+ repository, you can roll back the changeset there, too, but
+ you really should not expect this to work reliably. Sooner or
+ later a change really will make it into a repository that you
+ don't directly control (or have forgotten about), and come
+ back to bite you.)</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id391000">You can only roll back once</h3></div></div></div><p id="x_e0"><a name="x_e0"></a>Mercurial stores exactly one transaction in its
+ transaction log; that transaction is the most recent one that
+ occurred in the repository. This means that you can only roll
+ back one transaction. If you expect to be able to roll back
+ one transaction, then its predecessor, this is not the
+ behavior you will get.</p><pre id="id391424" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg rollback</code></strong>
+
+rolling back last transaction
+<code class="prompt">$</code> <strong class="userinput"><code>hg rollback</code></strong>
+no rollback information available
+</pre><p id="x_e1"><a name="x_e1"></a>Once you've rolled back one transaction in a repository,
+ you can't roll back again in that repository until you perform
+ another commit or pull.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id391367">Reverting the mistaken change</h2></div></div></div><p id="x_e2"><a name="x_e2"></a>If you make a modification to a file, and decide that you
+ really didn't want to change the file at all, and you haven't
+ yet committed your changes, the <span class="command"><strong>hg
+ revert</strong></span> command is the one you'll need. It looks at
+ the changeset that's the parent of the working directory, and
+ restores the contents of the file to their state as of that
+ changeset. (That's a long-winded way of saying that, in the
+ normal case, it undoes your modifications.)</p><p id="x_e3"><a name="x_e3"></a>Let's illustrate how the <span class="command"><strong>hg
+ revert</strong></span> command works with yet another small example.
+ We'll begin by modifying a file that Mercurial is already
+ tracking.</p><pre id="id391316" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat file</code></strong>
+
+original content
+<code class="prompt">$</code> <strong class="userinput"><code>echo unwanted change >> file</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg diff file</code></strong>
+diff -r b52afd4afc59 file
+--- a/file Tue May 05 06:55:32 2009 +0000
++++ b/file Tue May 05 06:55:32 2009 +0000
+@@ -1,1 +1,2 @@
+ original content
++unwanted change
+</pre><p id="x_e4"><a name="x_e4"></a>If we don't
+ want that change, we can simply <span class="command"><strong>hg
+ revert</strong></span> the file.</p><pre id="id391251" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
+
+M file
+<code class="prompt">$</code> <strong class="userinput"><code>hg revert file</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>cat file</code></strong>
+original content
+</pre><p id="x_e5"><a name="x_e5"></a>The <span class="command"><strong>hg revert</strong></span> command
+ provides us with an extra degree of safety by saving our
+ modified file with a <code class="filename">.orig</code>
+ extension.</p><pre id="id391767" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
+
+? file.orig
+<code class="prompt">$</code> <strong class="userinput"><code>cat file.orig</code></strong>
+original content
+unwanted change
+</pre><div class="tip"><table border="0" summary="Tip: Be careful with .orig files"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="/support/figs/tip.png"></td><th align="left">Be careful with .orig files</th></tr><tr><td align="left" valign="top"><p id="x_6b8"><a name="x_6b8"></a>It's extremely unlikely that you are either using
+ Mercurial to manage files with <code class="filename">.orig</code>
+ extensions or that you even care about the contents of such
+ files. Just in case, though, it's useful to remember that
+ <span class="command"><strong>hg revert</strong></span> will
+ unconditionally overwrite an existing file with a
+ <code class="filename">.orig</code> extension. For instance, if you
+ already have a file named <code class="filename">foo.orig</code> when
+ you revert <code class="filename">foo</code>, the contents of
+ <code class="filename">foo.orig</code> will be clobbered.</p></td></tr></table></div><p id="x_e6"><a name="x_e6"></a>Here is a summary of the cases that the <span class="command"><strong>hg revert</strong></span> command can deal with. We
+ will describe each of these in more detail in the section that
+ follows.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_e7"><a name="x_e7"></a>If you modify a file, it will restore the file
+ to its unmodified state.</p></li><li><p id="x_e8"><a name="x_e8"></a>If you <span class="command"><strong>hg add</strong></span> a
+ file, it will undo the “<span class="quote">added</span>” state of the
+ file, but leave the file itself untouched.</p></li><li><p id="x_e9"><a name="x_e9"></a>If you delete a file without telling Mercurial,
+ it will restore the file to its unmodified contents.</p></li><li><p id="x_ea"><a name="x_ea"></a>If you use the <span class="command"><strong>hg
+ remove</strong></span> command to remove a file, it will undo
+ the “<span class="quote">removed</span>” state of the file, and restore
+ the file to its unmodified contents.</p></li></ul></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="sec:undo:mgmt">File management errors</h3></div></div></div><p id="x_eb"><a name="x_eb"></a>The <span class="command"><strong>hg revert</strong></span> command is
+ useful for more than just modified files. It lets you reverse
+ the results of all of Mercurial's file management
+ commands—<span class="command"><strong>hg add</strong></span>,
+ <span class="command"><strong>hg remove</strong></span>, and so on.</p><p id="x_ec"><a name="x_ec"></a>If you <span class="command"><strong>hg add</strong></span> a file,
+ then decide that in fact you don't want Mercurial to track it,
+ use <span class="command"><strong>hg revert</strong></span> to undo the
+ add. Don't worry; Mercurial will not modify the file in any
+ way. It will just “<span class="quote">unmark</span>” the file.</p><pre id="id391756" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo oops > oops</code></strong>
+
+<code class="prompt">$</code> <strong class="userinput"><code>hg add oops</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg status oops</code></strong>
+A oops
+<code class="prompt">$</code> <strong class="userinput"><code>hg revert oops</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
+
+? oops
+</pre><p id="x_ed"><a name="x_ed"></a>Similarly, if you ask Mercurial to <span class="command"><strong>hg remove</strong></span> a file, you can use
+ <span class="command"><strong>hg revert</strong></span> to restore it to
+ the contents it had as of the parent of the working directory.
+
+</p><pre id="id392036" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg remove file</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
+R file
+
+<code class="prompt">$</code> <strong class="userinput"><code>hg revert file</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>ls file</code></strong>
+file
+</pre><p>
+
+ This works just as
+ well for a file that you deleted by hand, without telling
+ Mercurial (recall that in Mercurial terminology, this kind of
+ file is called “<span class="quote">missing</span>”).</p><pre id="id391954" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>rm file</code></strong>
+
+<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
+! file
+<code class="prompt">$</code> <strong class="userinput"><code>hg revert file</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>ls file</code></strong>
+file
+</pre><p id="x_ee"><a name="x_ee"></a>If you revert a <span class="command"><strong>hg copy</strong></span>,
+ the copied-to file remains in your working directory
+ afterwards, untracked. Since a copy doesn't affect the
+ copied-from file in any way, Mercurial doesn't do anything
+ with the copied-from file.</p><pre id="id392181" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg copy file new-file</code></strong>
+
+<code class="prompt">$</code> <strong class="userinput"><code>hg revert new-file</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg status</code></strong>
+? new-file
+</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id392218">Dealing with committed changes</h2></div></div></div><p id="x_f5"><a name="x_f5"></a>Consider a case where you have committed a change
+ <span class="emphasis"><em>a</em></span>, and another change
+ <span class="emphasis"><em>b</em></span> on top of it; you then realise that
+ change <span class="emphasis"><em>a</em></span> was incorrect. Mercurial lets you
+ “<span class="quote">back out</span>” an entire changeset automatically, and
+ building blocks that let you reverse part of a changeset by
+ hand.</p><p id="x_f6"><a name="x_f6"></a>Before you read this section, here's something to
+ keep in mind: the <span class="command"><strong>hg backout</strong></span>
+
+ command undoes the effect of a change by
+ <span class="emphasis"><em>adding</em></span> to your repository's history, not by
+ modifying or erasing it. It's the right tool to use if you're
+ fixing bugs, but not if you're trying to undo some change that
+ has catastrophic consequences. To deal with those, see
+ <a class="xref" href="finding-and-fixing-mistakes.html#sec:undo:aaaiiieee" title="Changes that should never have been">the section called “Changes that should never have been”</a>.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id392287">Backing out a changeset</h3></div></div></div><p id="x_f7"><a name="x_f7"></a>The <span class="command"><strong>hg backout</strong></span> command
+ lets you “<span class="quote">undo</span>” the effects of an entire
+ changeset in an automated fashion. Because Mercurial's
+ history is immutable, this command <span class="emphasis"><em>does
+ not</em></span> get rid of the changeset you want to undo.
+ Instead, it creates a new changeset that
+ <span class="emphasis"><em>reverses</em></span> the effect of the to-be-undone
+ changeset.</p><p id="x_f8"><a name="x_f8"></a>The operation of the <span class="command"><strong>hg
+ backout</strong></span> command is a little intricate, so let's
+ illustrate it with some examples. First, we'll create a
+ repository with some simple changes.</p><pre id="id392685" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init myrepo</code></strong>
+
+<code class="prompt">$</code> <strong class="userinput"><code>cd myrepo</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>echo first change >> myfile</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg add myfile</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'first change'</code></strong>
+
+<code class="prompt">$</code> <strong class="userinput"><code>echo second change >> myfile</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'second change'</code></strong>
+</pre><p id="x_f9"><a name="x_f9"></a>The <span class="command"><strong>hg backout</strong></span> command
+ takes a single changeset ID as its argument; this is the
+ changeset to back out. Normally, <span class="command"><strong>hg
+ backout</strong></span> will drop you into a text editor to write
+ a commit message, so you can record why you're backing the
+ change out. In this example, we provide a commit message on
+ the command line using the <code class="option">-m</code> option.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id392424">Backing out the tip changeset</h3></div></div></div><p id="x_fa"><a name="x_fa"></a>We're going to start by backing out the last changeset we
+ committed.</p><pre id="id392577" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg backout -m 'back out second change' tip</code></strong>
+
+reverting myfile
+changeset 2:01adc4672142 backs out changeset 1:7e341ee3be7a
+<code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
+first change
+</pre><p id="x_fb"><a name="x_fb"></a>You can see that the second line from
+ <code class="filename">myfile</code> is no longer present. Taking a
+ look at the output of <span class="command"><strong>hg log</strong></span>
+ gives us an idea of what the <span class="command"><strong>hg
+ backout</strong></span> command has done.
+
+
+</p><pre id="id392554" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log --style compact</code></strong>
+2[tip] 01adc4672142 2009-05-05 06:55 +0000 bos
+ back out second change
+
+1 7e341ee3be7a 2009-05-05 06:55 +0000 bos
+ second change
+
+0 56b97fc928f2 2009-05-05 06:55 +0000 bos
+ first change
+
+</pre><p>
+
+ Notice that the new changeset
+ that <span class="command"><strong>hg backout</strong></span> has created
+ is a child of the changeset we backed out. It's easier to see
+ this in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:backout" title="Figure 9.1. Backing out a change using the hg backout command">Figure 9.1, “Backing out a change using the hg backout command”</a>, which presents a
+ graphical view of the change history. As you can see, the
+ history is nice and linear.</p><div class="figure"><a name="fig:undo:backout"></a><p class="title"><b>Figure 9.1. Backing out a change using the <span class="command">hg backout</span> command</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/undo-simple.png" alt="XXX add text"></div></div></div><br class="figure-break"></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id392766">Backing out a non-tip change</h3></div></div></div><p id="x_fd"><a name="x_fd"></a>If you want to back out a change other than the last one
+ you committed, pass the <code class="option">--merge</code> option to the
+ <span class="command"><strong>hg backout</strong></span> command.</p><pre id="id393141" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
+
+<code class="prompt">$</code> <strong class="userinput"><code>hg clone -r1 myrepo non-tip-repo</code></strong>
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 2 changesets with 2 changes to 1 files
+updating working directory
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+<code class="prompt">$</code> <strong class="userinput"><code>cd non-tip-repo</code></strong>
+</pre><p id="x_fe"><a name="x_fe"></a>This makes backing out any changeset a
+ “<span class="quote">one-shot</span>” operation that's usually simple and
+ fast.</p><pre id="id392845" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo third change >> myfile</code></strong>
+
+<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'third change'</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg backout --merge -m 'back out second change' 1</code></strong>
+reverting myfile
+created new head
+changeset 3:abc7fd860049 backs out changeset 1:7e341ee3be7a
+merging with changeset 3:abc7fd860049
+merging myfile
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+</pre><p id="x_ff"><a name="x_ff"></a>If you take a look at the contents of
+ <code class="filename">myfile</code> after the backout finishes, you'll
+ see that the first and third changes are present, but not the
+ second.</p><pre id="id392886" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
+
+first change
+third change
+</pre><p id="x_100"><a name="x_100"></a>As the graphical history in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:backout-non-tip" title="Figure 9.2. Automated backout of a non-tip change using the hg backout command">Figure 9.2, “Automated backout of a non-tip change using the
+ hg backout command”</a> illustrates, Mercurial
+ still commits one change in this kind of situation (the
+ box-shaped node is the ones that Mercurial commits
+ automatically), but the revision graph now looks different.
+ Before Mercurial begins the backout process, it first
+ remembers what the current parent of the working directory is.
+ It then backs out the target changeset, and commits that as a
+ changeset. Finally, it merges back to the previous parent of
+ the working directory, but notice that it <span class="emphasis"><em>does not
+ commit</em></span> the result of the merge. The repository
+ now contains two heads, and the working directory is in a
+ merge state.</p><div class="figure"><a name="fig:undo:backout-non-tip"></a><p class="title"><b>Figure 9.2. Automated backout of a non-tip change using the
+ <span class="command">hg backout</span> command</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/undo-non-tip.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_103"><a name="x_103"></a>The result is that you end up “<span class="quote">back where you
+ were</span>”, only with some extra history that undoes the
+ effect of the changeset you wanted to back out.</p><p id="x_6b9"><a name="x_6b9"></a>You might wonder why Mercurial does not commit the result
+ of the merge that it performed. The reason lies in Mercurial
+ behaving conservatively: a merge naturally has more scope for
+ error than simply undoing the effect of the tip changeset,
+ so your work will be safest if you first inspect (and test!)
+ the result of the merge, <span class="emphasis"><em>then</em></span> commit
+ it.</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title" id="id392990">Always use the <code class="option">--merge</code> option</h4></div></div></div><p id="x_104"><a name="x_104"></a>In fact, since the <code class="option">--merge</code> option will do the
+ “<span class="quote">right thing</span>” whether or not the changeset
+ you're backing out is the tip (i.e. it won't try to merge if
+ it's backing out the tip, since there's no need), you should
+ <span class="emphasis"><em>always</em></span> use this option when you run the
+ <span class="command"><strong>hg backout</strong></span> command.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id393181">Gaining more control of the backout process</h3></div></div></div><p id="x_105"><a name="x_105"></a>While I've recommended that you always use the <code class="option">--merge</code> option when backing
+ out a change, the <span class="command"><strong>hg backout</strong></span>
+
+ command lets you decide how to merge a backout changeset.
+ Taking control of the backout process by hand is something you
+ will rarely need to do, but it can be useful to understand
+ what the <span class="command"><strong>hg backout</strong></span> command
+ is doing for you automatically. To illustrate this, let's
+ clone our first repository, but omit the backout change that
+ it contains.</p><pre id="id393568" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cd ..</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg clone -r1 myrepo newrepo</code></strong>
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 2 changesets with 2 changes to 1 files
+updating working directory
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+<code class="prompt">$</code> <strong class="userinput"><code>cd newrepo</code></strong>
+
+</pre><p id="x_106"><a name="x_106"></a>As with our
+ earlier example, We'll commit a third changeset, then back out
+ its parent, and see what happens.</p><pre id="id393553" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>echo third change >> myfile</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'third change'</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>hg backout -m 'back out second change' 1</code></strong>
+reverting myfile
+created new head
+changeset 3:abc7fd860049 backs out changeset 1:7e341ee3be7a
+the backout changeset is a new head - do not forget to merge
+(use "backout --merge" if you want to auto-merge)
+</pre><p id="x_107"><a name="x_107"></a>Our new changeset is again a descendant of the changeset
+ we backout out; it's thus a new head, <span class="emphasis"><em>not</em></span>
+
+ a descendant of the changeset that was the tip. The <span class="command"><strong>hg backout</strong></span> command was quite
+ explicit in telling us this.</p><pre id="id393314" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg log --style compact</code></strong>
+3[tip]:1 abc7fd860049 2009-05-05 06:55 +0000 bos
+ back out second change
+
+2 bae4005ddac4 2009-05-05 06:55 +0000 bos
+ third change
+
+1 7e341ee3be7a 2009-05-05 06:55 +0000 bos
+ second change
+
+0 56b97fc928f2 2009-05-05 06:55 +0000 bos
+ first change
+
+</pre><p id="x_108"><a name="x_108"></a>Again, it's easier to see what has happened by looking at
+ a graph of the revision history, in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:backout-manual" title="Figure 9.3. Backing out a change using the hg backout command">Figure 9.3, “Backing out a change using the hg backout command”</a>. This makes it clear
+ that when we use <span class="command"><strong>hg backout</strong></span>
+ to back out a change other than the tip, Mercurial adds a new
+ head to the repository (the change it committed is
+ box-shaped).</p><div class="figure"><a name="fig:undo:backout-manual"></a><p class="title"><b>Figure 9.3. Backing out a change using the <span class="command">hg backout</span> command</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/undo-manual.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_10a"><a name="x_10a"></a>After the <span class="command"><strong>hg backout</strong></span>
+
+ command has completed, it leaves the new
+ “<span class="quote">backout</span>” changeset as the parent of the working
+ directory.</p><pre id="id393912" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg parents</code></strong>
+changeset: 2:bae4005ddac4
+user: Bryan O'Sullivan <bos@serpentine.com>
+date: Tue May 05 06:55:12 2009 +0000
+summary: third change
+
+</pre><p id="x_10b"><a name="x_10b"></a>Now we have two isolated sets of changes.</p><pre id="id393905" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg heads</code></strong>
+
+changeset: 3:abc7fd860049
+tag: tip
+parent: 1:7e341ee3be7a
+user: Bryan O'Sullivan <bos@serpentine.com>
+date: Tue May 05 06:55:12 2009 +0000
+summary: back out second change
+
+changeset: 2:bae4005ddac4
+user: Bryan O'Sullivan <bos@serpentine.com>
+date: Tue May 05 06:55:12 2009 +0000
+summary: third change
+
+</pre><p id="x_10c"><a name="x_10c"></a>Let's think about what we expect to see as the contents of
+ <code class="filename">myfile</code> now. The first change should be
+ present, because we've never backed it out. The second change
+ should be missing, as that's the change we backed out. Since
+ the history graph shows the third change as a separate head,
+ we <span class="emphasis"><em>don't</em></span> expect to see the third change
+ present in <code class="filename">myfile</code>.</p><pre id="id393884" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
+
+first change
+</pre><p id="x_10d"><a name="x_10d"></a>To get the third change back into the file, we just do a
+ normal merge of our two heads.</p><pre id="id393845" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg merge</code></strong>
+abort: outstanding uncommitted changes
+<code class="prompt">$</code> <strong class="userinput"><code>hg commit -m 'merged backout with previous tip'</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>cat myfile</code></strong>
+first change
+</pre><p id="x_10e"><a name="x_10e"></a>Afterwards, the graphical history of our
+ repository looks like
+ <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:backout-manual-merge" title="Figure 9.4. Manually merging a backout change">Figure 9.4, “Manually merging a backout change”</a>.</p><div class="figure"><a name="fig:undo:backout-manual-merge"></a><p class="title"><b>Figure 9.4. Manually merging a backout change</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/undo-manual-merge.png" alt="XXX add text"></div></div></div><br class="figure-break"></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id393814">Why <span class="command"><strong>hg backout</strong></span> works as
+ it does</h3></div></div></div><p id="x_110"><a name="x_110"></a>Here's a brief description of how the <span class="command"><strong>hg backout</strong></span> command works.</p><div class="orderedlist"><ol type="1"><li><p id="x_111"><a name="x_111"></a>It ensures that the working directory is
+ “<span class="quote">clean</span>”, i.e. that the output of <span class="command"><strong>hg status</strong></span> would be empty.</p></li><li><p id="x_112"><a name="x_112"></a>It remembers the current parent of the working
+ directory. Let's call this changeset
+ <code class="literal">orig</code>.</p></li><li><p id="x_113"><a name="x_113"></a>It does the equivalent of a <span class="command"><strong>hg update</strong></span> to sync the working
+ directory to the changeset you want to back out. Let's
+ call this changeset <code class="literal">backout</code>.</p></li><li><p id="x_114"><a name="x_114"></a>It finds the parent of that changeset. Let's
+ call that changeset <code class="literal">parent</code>.</p></li><li><p id="x_115"><a name="x_115"></a>For each file that the
+ <code class="literal">backout</code> changeset affected, it does the
+ equivalent of a <span class="command"><strong>hg revert -r
+ parent</strong></span> on that file, to restore it to the
+ contents it had before that changeset was
+ committed.</p></li><li><p id="x_116"><a name="x_116"></a>It commits the result as a new changeset.
+ This changeset has <code class="literal">backout</code> as its
+ parent.</p></li><li><p id="x_117"><a name="x_117"></a>If you specify <code class="option">--merge</code> on the command
+ line, it merges with <code class="literal">orig</code>, and commits
+ the result of the merge.</p></li></ol></div><p id="x_118"><a name="x_118"></a>An alternative way to implement the <span class="command"><strong>hg backout</strong></span> command would be to
+ <span class="command"><strong>hg export</strong></span> the
+ to-be-backed-out changeset as a diff, then use the <code class="option">--reverse</code> option to the
+ <span class="command"><strong>patch</strong></span> command to reverse the effect of the
+ change without fiddling with the working directory. This
+ sounds much simpler, but it would not work nearly as
+ well.</p><p id="x_119"><a name="x_119"></a>The reason that <span class="command"><strong>hg
+ backout</strong></span> does an update, a commit, a merge, and
+ another commit is to give the merge machinery the best chance
+ to do a good job when dealing with all the changes
+ <span class="emphasis"><em>between</em></span> the change you're backing out and
+ the current tip.</p><p id="x_11a"><a name="x_11a"></a>If you're backing out a changeset that's 100 revisions
+ back in your project's history, the chances that the
+ <span class="command"><strong>patch</strong></span> command will be able to apply a
+ reverse diff cleanly are not good, because intervening changes
+ are likely to have “<span class="quote">broken the context</span>” that
+ <span class="command"><strong>patch</strong></span> uses to determine whether it can
+ apply a patch (if this sounds like gibberish, see <a class="xref" href="managing-change-with-mercurial-queues.html#sec:mq:patch" title="Understanding patches">the section called “Understanding patches”</a> for a
+ discussion of the <span class="command"><strong>patch</strong></span> command). Also,
+ Mercurial's merge machinery will handle files and directories
+ being renamed, permission changes, and modifications to binary
+ files, none of which <span class="command"><strong>patch</strong></span> can deal
+ with.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:undo:aaaiiieee">Changes that should never have been</h2></div></div></div><p id="x_11b"><a name="x_11b"></a>Most of the time, the <span class="command"><strong>hg
+ backout</strong></span> command is exactly what you need if you want
+ to undo the effects of a change. It leaves a permanent record
+ of exactly what you did, both when committing the original
+ changeset and when you cleaned up after it.</p><p id="x_11c"><a name="x_11c"></a>On rare occasions, though, you may find that you've
+ committed a change that really should not be present in the
+ repository at all. For example, it would be very unusual, and
+ usually considered a mistake, to commit a software project's
+ object files as well as its source files. Object files have
+ almost no intrinsic value, and they're <span class="emphasis"><em>big</em></span>,
+ so they increase the size of the repository and the amount of
+ time it takes to clone or pull changes.</p><p id="x_11d"><a name="x_11d"></a>Before I discuss the options that you have if you commit a
+ “<span class="quote">brown paper bag</span>” change (the kind that's so bad
+ that you want to pull a brown paper bag over your head), let me
+ first discuss some approaches that probably won't work.</p><p id="x_11e"><a name="x_11e"></a>Since Mercurial treats history as
+ accumulative—every change builds on top of all changes
+ that preceded it—you generally can't just make disastrous
+ changes disappear. The one exception is when you've just
+ committed a change, and it hasn't been pushed or pulled into
+ another repository. That's when you can safely use the <span class="command"><strong>hg rollback</strong></span> command, as I detailed in
+ <a class="xref" href="finding-and-fixing-mistakes.html#sec:undo:rollback" title="Rolling back a transaction">the section called “Rolling back a transaction”</a>.</p><p id="x_11f"><a name="x_11f"></a>After you've pushed a bad change to another repository, you
+ <span class="emphasis"><em>could</em></span> still use <span class="command"><strong>hg
+ rollback</strong></span> to make your local copy of the change
+ disappear, but it won't have the consequences you want. The
+ change will still be present in the remote repository, so it
+ will reappear in your local repository the next time you
+ pull.</p><p id="x_120"><a name="x_120"></a>If a situation like this arises, and you know which
+ repositories your bad change has propagated into, you can
+ <span class="emphasis"><em>try</em></span> to get rid of the change from
+ <span class="emphasis"><em>every</em></span> one of those repositories. This is,
+ of course, not a satisfactory solution: if you miss even a
+ single repository while you're expunging, the change is still
+ “<span class="quote">in the wild</span>”, and could propagate further.</p><p id="x_121"><a name="x_121"></a>If you've committed one or more changes
+ <span class="emphasis"><em>after</em></span> the change that you'd like to see
+ disappear, your options are further reduced. Mercurial doesn't
+ provide a way to “<span class="quote">punch a hole</span>” in history, leaving
+ changesets intact.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id394303">Backing out a merge</h3></div></div></div><p id="x_6ba"><a name="x_6ba"></a>Since merges are often complicated, it is not unheard of
+ for a merge to be mangled badly, but committed erroneously.
+ Mercurial provides an important safeguard against bad merges
+ by refusing to commit unresolved files, but human ingenuity
+ guarantees that it is still possible to mess a merge up and
+ commit it.</p><p id="x_6bb"><a name="x_6bb"></a>Given a bad merge that has been committed, usually the
+ best way to approach it is to simply try to repair the damage
+ by hand. A complete disaster that cannot be easily fixed up
+ by hand ought to be very rare, but the <span class="command"><strong>hg backout</strong></span> command may help in
+ making the cleanup easier. It offers a <code class="option">--parent</code> option, which lets
+ you specify which parent to revert to when backing out a
+ merge.</p><div class="figure"><a name="fig:undo:bad-merge-1"></a><p class="title"><b>Figure 9.5. A bad merge</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/bad-merge-1.png" alt="XXX add text"></div></div></div><br class="figure-break"><p id="x_6bc"><a name="x_6bc"></a>Suppose we have a revision graph like that in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:bad-merge-1" title="Figure 9.5. A bad merge">Figure 9.5, “A bad merge”</a>. What we'd like is to
+ <span class="emphasis"><em>redo</em></span> the merge of revisions 2 and
+ 3.</p><p id="x_6bd"><a name="x_6bd"></a>One way to do so would be as follows.</p><div class="orderedlist"><ol type="1"><li><p id="x_6be"><a name="x_6be"></a>Call <span class="command"><strong>hg backout --rev=4
+ --parent=2</strong></span>. This tells <span class="command"><strong>hg backout</strong></span> to back out revision
+ 4, which is the bad merge, and to when deciding which
+ revision to prefer, to choose parent 2, one of the parents
+ of the merge. The effect can be seen in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:bad-merge-2" title="Figure 9.6. Backing out the merge, favoring one parent">Figure 9.6, “Backing out the merge, favoring one parent”</a>.</p><div class="figure"><a name="fig:undo:bad-merge-2"></a><p class="title"><b>Figure 9.6. Backing out the merge, favoring one parent</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/bad-merge-2.png" alt="XXX add text"></div></div></div><br class="figure-break"></li><li><p id="x_6bf"><a name="x_6bf"></a>Call <span class="command"><strong>hg backout --rev=4
+ --parent=3</strong></span>. This tells <span class="command"><strong>hg backout</strong></span> to back out revision
+ 4 again, but this time to choose parent 3, the other
+ parent of the merge. The result is visible in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:bad-merge-3" title="Figure 9.7. Backing out the merge, favoring the other parent">Figure 9.7, “Backing out the merge, favoring the other
+ parent”</a>, in which the repository
+ now contains three heads.</p><div class="figure"><a name="fig:undo:bad-merge-3"></a><p class="title"><b>Figure 9.7. Backing out the merge, favoring the other
+ parent</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/bad-merge-3.png" alt="XXX add text"></div></div></div><br class="figure-break"></li><li><p id="x_6c0"><a name="x_6c0"></a>Redo the bad merge by merging the two backout heads,
+ which reduces the number of heads in the repository to
+ two, as can be seen in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:bad-merge-4" title="Figure 9.8. Merging the backouts">Figure 9.8, “Merging the backouts”</a>.</p><div class="figure"><a name="fig:undo:bad-merge-4"></a><p class="title"><b>Figure 9.8. Merging the backouts</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/bad-merge-4.png" alt="XXX add text"></div></div></div><br class="figure-break"></li><li><p id="x_6c1"><a name="x_6c1"></a>Merge with the commit that was made after the bad
+ merge, as shown in <a class="xref" href="finding-and-fixing-mistakes.html#fig:undo:bad-merge-5" title="Figure 9.9. Merging the backouts">Figure 9.9, “Merging the backouts”</a>.</p><div class="figure"><a name="fig:undo:bad-merge-5"></a><p class="title"><b>Figure 9.9. Merging the backouts</b></p><div class="figure-contents"><div class="mediaobject"><img src="figs/bad-merge-5.png" alt="XXX add text"></div></div></div><br class="figure-break"></li></ol></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id394612">Protect yourself from “<span class="quote">escaped</span>”
+ changes</h3></div></div></div><p id="x_123"><a name="x_123"></a>If you've committed some changes to your local repository
+ and they've been pushed or pulled somewhere else, this isn't
+ necessarily a disaster. You can protect yourself ahead of
+ time against some classes of bad changeset. This is
+ particularly easy if your team usually pulls changes from a
+ central repository.</p><p id="x_124"><a name="x_124"></a>By configuring some hooks on that repository to validate
+ incoming changesets (see chapter <a class="xref" href="handling-repository-events-with-hooks.html" title="Chapter 10. Handling repository events with hooks">Chapter 10, <i>Handling repository events with hooks</i></a>),
+ you can
+ automatically prevent some kinds of bad changeset from being
+ pushed to the central repository at all. With such a
+ configuration in place, some kinds of bad changeset will
+ naturally tend to “<span class="quote">die out</span>” because they can't
+ propagate into the central repository. Better yet, this
+ happens without any need for explicit intervention.</p><p id="x_125"><a name="x_125"></a>For instance, an incoming change hook that
+ verifies that a changeset will actually compile can prevent
+ people from inadvertently “<span class="quote">breaking the
+ build</span>”.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id394667">What to do about sensitive changes that escape</h3></div></div></div><p id="x_6c2"><a name="x_6c2"></a>Even a carefully run project can suffer an unfortunate
+ event such as the committing and uncontrolled propagation of a
+ file that contains important passwords.</p><p id="x_6c3"><a name="x_6c3"></a>If something like this happens to you, and the information
+ that gets accidentally propagated is truly sensitive, your
+ first step should be to mitigate the effect of the leak
+ without trying to control the leak itself. If you are not 100%
+ certain that you know exactly who could have seen the changes,
+ you should immediately change passwords, cancel credit cards,
+ or find some other way to make sure that the information that
+ has leaked is no longer useful. In other words, assume that
+ the change has propagated far and wide, and that there's
+ nothing more you can do.</p><p id="x_6c4"><a name="x_6c4"></a>You might hope that there would be mechanisms you could
+ use to either figure out who has seen a change or to erase the
+ change permanently everywhere, but there are good reasons why
+ these are not possible.</p><p id="x_6c5"><a name="x_6c5"></a>Mercurial does not provide an audit trail of who has
+ pulled changes from a repository, because it is usually either
+ impossible to record such information or trivial to spoof it.
+ In a multi-user or networked environment, you should thus be
+ extremely skeptical of yourself if you think that you have
+ identified every place that a sensitive changeset has
+ propagated to. Don't forget that people can and will send
+ bundles by email, have their backup software save data
+ offsite, carry repositories on USB sticks, and find other
+ completely innocent ways to confound your attempts to track
+ down every copy of a problematic change.</p><p id="x_6c6"><a name="x_6c6"></a>Mercurial also does not provide a way to make a file or
+ changeset completely disappear from history, because there is
+ no way to enforce its disappearance; someone could easily
+ modify their copy of Mercurial to ignore such directives. In
+ addition, even if Mercurial provided such a capability,
+ someone who simply hadn't pulled a “<span class="quote">make this file
+ disappear</span>” changeset wouldn't be affected by it, nor
+ would web crawlers visiting at the wrong time, disk backups,
+ or other mechanisms. Indeed, no distributed revision control
+ system can make data reliably vanish. Providing the illusion
+ of such control could easily give a false sense of security,
+ and be worse than not providing it at all.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="sec:undo:bisect">Finding the source of a bug</h2></div></div></div><p id="x_126"><a name="x_126"></a>While it's all very well to be able to back out a changeset
+ that introduced a bug, this requires that you know which
+ changeset to back out. Mercurial provides an invaluable
+ command, called <span class="command"><strong>hg bisect</strong></span>, that
+ helps you to automate this process and accomplish it very
+ efficiently.</p><p id="x_127"><a name="x_127"></a>The idea behind the <span class="command"><strong>hg
+ bisect</strong></span> command is that a changeset has introduced
+ some change of behavior that you can identify with a simple
+ pass/fail test. You don't know which piece of code introduced the
+ change, but you know how to test for the presence of the bug.
+ The <span class="command"><strong>hg bisect</strong></span> command uses your
+ test to direct its search for the changeset that introduced the
+ code that caused the bug.</p><p id="x_128"><a name="x_128"></a>Here are a few scenarios to help you understand how you
+ might apply this command.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_129"><a name="x_129"></a>The most recent version of your software has a
+ bug that you remember wasn't present a few weeks ago, but
+ you don't know when it was introduced. Here, your binary
+ test checks for the presence of that bug.</p></li><li><p id="x_12a"><a name="x_12a"></a>You fixed a bug in a rush, and now it's time to
+ close the entry in your team's bug database. The bug
+ database requires a changeset ID when you close an entry,
+ but you don't remember which changeset you fixed the bug in.
+ Once again, your binary test checks for the presence of the
+ bug.</p></li><li><p id="x_12b"><a name="x_12b"></a>Your software works correctly, but runs 15%
+ slower than the last time you measured it. You want to know
+ which changeset introduced the performance regression. In
+ this case, your binary test measures the performance of your
+ software, to see whether it's “<span class="quote">fast</span>” or
+ “<span class="quote">slow</span>”.</p></li><li><p id="x_12c"><a name="x_12c"></a>The sizes of the components of your project that
+ you ship exploded recently, and you suspect that something
+ changed in the way you build your project.</p></li></ul></div><p id="x_12d"><a name="x_12d"></a>From these examples, it should be clear that the <span class="command"><strong>hg bisect</strong></span> command is not useful only
+ for finding the sources of bugs. You can use it to find any
+ “<span class="quote">emergent property</span>” of a repository (anything that
+ you can't find from a simple text search of the files in the
+ tree) for which you can write a binary test.</p><p id="x_12e"><a name="x_12e"></a>We'll introduce a little bit of terminology here, just to
+ make it clear which parts of the search process are your
+ responsibility, and which are Mercurial's. A
+ <span class="emphasis"><em>test</em></span> is something that
+ <span class="emphasis"><em>you</em></span> run when <span class="command"><strong>hg
+ bisect</strong></span> chooses a changeset. A
+ <span class="emphasis"><em>probe</em></span> is what <span class="command"><strong>hg
+ bisect</strong></span> runs to tell whether a revision is good.
+ Finally, we'll use the word “<span class="quote">bisect</span>”, as both a
+ noun and a verb, to stand in for the phrase “<span class="quote">search using
+ the <span class="command"><strong>hg bisect</strong></span>
+
+ command</span>”.</p><p id="x_12f"><a name="x_12f"></a>One simple way to automate the searching process would be
+ simply to probe every changeset. However, this scales poorly.
+ If it took ten minutes to test a single changeset, and you had
+ 10,000 changesets in your repository, the exhaustive approach
+ would take on average 35 <span class="emphasis"><em>days</em></span> to find the
+ changeset that introduced a bug. Even if you knew that the bug
+ was introduced by one of the last 500 changesets, and limited
+ your search to those, you'd still be looking at over 40 hours to
+ find the changeset that introduced your bug.</p><p id="x_130"><a name="x_130"></a>What the <span class="command"><strong>hg bisect</strong></span> command
+ does is use its knowledge of the “<span class="quote">shape</span>” of your
+ project's revision history to perform a search in time
+ proportional to the <span class="emphasis"><em>logarithm</em></span> of the number
+ of changesets to check (the kind of search it performs is called
+ a dichotomic search). With this approach, searching through
+ 10,000 changesets will take less than three hours, even at ten
+ minutes per test (the search will require about 14 tests).
+ Limit your search to the last hundred changesets, and it will
+ take only about an hour (roughly seven tests).</p><p id="x_131"><a name="x_131"></a>The <span class="command"><strong>hg bisect</strong></span> command is
+ aware of the “<span class="quote">branchy</span>” nature of a Mercurial
+ project's revision history, so it has no problems dealing with
+ branches, merges, or multiple heads in a repository. It can
+ prune entire branches of history with a single probe, which is
+ how it operates so efficiently.</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id394992">Using the <span class="command"><strong>hg bisect</strong></span>
+
+ command</h3></div></div></div><p id="x_132"><a name="x_132"></a>Here's an example of <span class="command"><strong>hg
+ bisect</strong></span> in action.</p><div class="note"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="/support/figs/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p id="x_133"><a name="x_133"></a> In versions 0.9.5 and earlier of Mercurial, <span class="command"><strong>hg bisect</strong></span> was not a core command:
+ it was distributed with Mercurial as an extension. This
+ section describes the built-in command, not the old
+ extension.</p></td></tr></table></div><p id="x_134"><a name="x_134"></a>Now let's create a repository, so that we can try out the
+ <span class="command"><strong>hg bisect</strong></span> command in
+ isolation.</p><pre id="id395406" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg init mybug</code></strong>
+
+<code class="prompt">$</code> <strong class="userinput"><code>cd mybug</code></strong>
+</pre><p id="x_135"><a name="x_135"></a>We'll simulate a project that has a bug in it in a
+ simple-minded way: create trivial changes in a loop, and
+ nominate one specific change that will have the
+ “<span class="quote">bug</span>”. This loop creates 35 changesets, each
+ adding a single file to the repository. We'll represent our
+ “<span class="quote">bug</span>” with a file that contains the text “<span class="quote">i
+ have a gub</span>”.</p><pre id="id395397" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>buggy_change=22</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>for (( i = 0; i < 35; i++ )); do</code></strong>
+
+<code class="prompt">></code> <strong class="userinput"><code> if [[ $i = $buggy_change ]]; then</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> echo 'i have a gub' > myfile$i</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> hg commit -q -A -m 'buggy changeset'</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> else</code></strong>
+
+<code class="prompt">></code> <strong class="userinput"><code> echo 'nothing to see here, move along' > myfile$i</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> hg commit -q -A -m 'normal changeset'</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> fi</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code>done</code></strong>
+
+</pre><p id="x_136"><a name="x_136"></a>The next thing that we'd like to do is figure out how to
+ use the <span class="command"><strong>hg bisect</strong></span> command.
+ We can use Mercurial's normal built-in help mechanism for
+ this.</p><pre id="id395535" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg help bisect</code></strong>
+hg bisect [-gbsr] [-c CMD] [REV]
+
+subdivision search of changesets
+
+ This command helps to find changesets which introduce problems.
+ To use, mark the earliest changeset you know exhibits the problem
+ as bad, then mark the latest changeset which is free from the
+ problem as good. Bisect will update your working directory to a
+ revision for testing (unless the --noupdate option is specified).
+ Once you have performed tests, mark the working directory as bad
+ or good and bisect will either update to another candidate changeset
+ or announce that it has found the bad revision.
+
+ As a shortcut, you can also use the revision argument to mark a
+ revision as good or bad without checking it out first.
+
+ If you supply a command it will be used for automatic bisection. Its exit
+ status will be used as flag to mark revision as bad or good. In case exit
+ status is 0 the revision is marked as good, 125 - skipped, 127 (command not
+ found) - bisection will be aborted; any other status bigger than 0 will
+ mark revision as bad.
+
+options:
+
+ -r --reset reset bisect state
+ -g --good mark changeset good
+ -b --bad mark changeset bad
+ -s --skip skip testing changeset
+ -c --command use command to check changeset state
+ -U --noupdate do not update to target
+
+use "hg -v help bisect" to show global options
+</pre><p id="x_137"><a name="x_137"></a>The <span class="command"><strong>hg bisect</strong></span> command
+ works in steps. Each step proceeds as follows.</p><div class="orderedlist"><ol type="1"><li><p id="x_138"><a name="x_138"></a>You run your binary test.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_139"><a name="x_139"></a>If the test succeeded, you tell <span class="command"><strong>hg bisect</strong></span> by running the
+ <span class="command"><strong>hg bisect --good</strong></span>
+
+ command.</p></li><li><p id="x_13a"><a name="x_13a"></a>If it failed, run the <span class="command"><strong>hg bisect --bad</strong></span>
+ command.</p></li></ul></div></li><li><p id="x_13b"><a name="x_13b"></a>The command uses your information to decide
+ which changeset to test next.</p></li><li><p id="x_13c"><a name="x_13c"></a>It updates the working directory to that
+ changeset, and the process begins again.</p></li></ol></div><p id="x_13d"><a name="x_13d"></a>The process ends when <span class="command"><strong>hg
+ bisect</strong></span> identifies a unique changeset that marks
+ the point where your test transitioned from
+ “<span class="quote">succeeding</span>” to “<span class="quote">failing</span>”.</p><p id="x_13e"><a name="x_13e"></a>To start the search, we must run the <span class="command"><strong>hg bisect --reset</strong></span> command.</p><pre id="id395968" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg bisect --reset</code></strong>
+
+</pre><p id="x_13f"><a name="x_13f"></a>In our case, the binary test we use is simple: we check to
+ see if any file in the repository contains the string “<span class="quote">i
+ have a gub</span>”. If it does, this changeset contains the
+ change that “<span class="quote">caused the bug</span>”. By convention, a
+ changeset that has the property we're searching for is
+ “<span class="quote">bad</span>”, while one that doesn't is
+ “<span class="quote">good</span>”.</p><p id="x_140"><a name="x_140"></a>Most of the time, the revision to which the working
+ directory is synced (usually the tip) already exhibits the
+ problem introduced by the buggy change, so we'll mark it as
+ “<span class="quote">bad</span>”.</p><pre id="id396047" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg bisect --bad</code></strong>
+</pre><p id="x_141"><a name="x_141"></a>Our next task is to nominate a changeset that we know
+ <span class="emphasis"><em>doesn't</em></span> have the bug; the <span class="command"><strong>hg bisect</strong></span> command will
+ “<span class="quote">bracket</span>” its search between the first pair of
+ good and bad changesets. In our case, we know that revision
+ 10 didn't have the bug. (I'll have more words about choosing
+ the first “<span class="quote">good</span>” changeset later.)</p><pre id="id396032" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg bisect --good 10</code></strong>
+
+Testing changeset 22:b8789808fc48 (24 changesets remaining, ~4 tests)
+0 files updated, 0 files merged, 12 files removed, 0 files unresolved
+</pre><p id="x_142"><a name="x_142"></a>Notice that this command printed some output.</p><div class="itemizedlist"><ul type="disc"><li><p id="x_143"><a name="x_143"></a>It told us how many changesets it must
+ consider before it can identify the one that introduced
+ the bug, and how many tests that will require.</p></li><li><p id="x_144"><a name="x_144"></a>It updated the working directory to the next
+ changeset to test, and told us which changeset it's
+ testing.</p></li></ul></div><p id="x_145"><a name="x_145"></a>We now run our test in the working directory. We use the
+ <span class="command"><strong>grep</strong></span> command to see if our
+ “<span class="quote">bad</span>” file is present in the working directory.
+ If it is, this revision is bad; if not, this revision is good.
+
+</p><pre id="id395911" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>if grep -q 'i have a gub' *</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code>then</code></strong>
+
+<code class="prompt">></code> <strong class="userinput"><code> result=bad</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code>else</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> result=good</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code>fi</code></strong>
+<code class="prompt">$</code> <strong class="userinput"><code>echo this revision is $result</code></strong>
+
+this revision is bad
+<code class="prompt">$</code> <strong class="userinput"><code>hg bisect --$result</code></strong>
+Testing changeset 16:e61fdddff53e (12 changesets remaining, ~3 tests)
+0 files updated, 0 files merged, 6 files removed, 0 files unresolved
+</pre><p>
+
+</p><p id="x_146"><a name="x_146"></a>This test looks like a perfect candidate for automation,
+ so let's turn it into a shell function.</p><pre id="id396435" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>mytest() {</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> if grep -q 'i have a gub' *</code></strong>
+
+<code class="prompt">></code> <strong class="userinput"><code> then</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> result=bad</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> else</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> result=good</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> fi</code></strong>
+
+<code class="prompt">></code> <strong class="userinput"><code> echo this revision is $result</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code> hg bisect --$result</code></strong>
+<code class="prompt">></code> <strong class="userinput"><code>}</code></strong>
+</pre><p id="x_147"><a name="x_147"></a>We can now run an entire test step with a single command,
+ <code class="literal">mytest</code>.</p><pre id="id396403" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>mytest</code></strong>
+
+this revision is good
+Testing changeset 19:706df39b003b (6 changesets remaining, ~2 tests)
+3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+</pre><p id="x_148"><a name="x_148"></a>A few more invocations of our canned test step command,
+ and we're done.</p><pre id="id396344" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>mytest</code></strong>
+this revision is good
+Testing changeset 20:bf7ea9a054e6 (3 changesets remaining, ~1 tests)
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+<code class="prompt">$</code> <strong class="userinput"><code>mytest</code></strong>
+this revision is good
+Testing changeset 21:921391dd45c1 (2 changesets remaining, ~1 tests)
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+<code class="prompt">$</code> <strong class="userinput"><code>mytest</code></strong>
+this revision is good
+The first bad revision is:
+changeset: 22:b8789808fc48
+user: Bryan O'Sullivan <bos@serpentine.com>
+
+date: Tue May 05 06:55:14 2009 +0000
+summary: buggy changeset
+
+</pre><p id="x_149"><a name="x_149"></a>Even though we had 40 changesets to search through, the
+ <span class="command"><strong>hg bisect</strong></span> command let us find
+ the changeset that introduced our “<span class="quote">bug</span>” with only
+ five tests. Because the number of tests that the <span class="command"><strong>hg bisect</strong></span> command performs grows
+ logarithmically with the number of changesets to search, the
+ advantage that it has over the “<span class="quote">brute force</span>”
+ search approach increases with every changeset you add.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396541">Cleaning up after your search</h3></div></div></div><p id="x_14a"><a name="x_14a"></a>When you're finished using the <span class="command"><strong>hg
+ bisect</strong></span> command in a repository, you can use the
+ <span class="command"><strong>hg bisect --reset</strong></span> command to
+ drop the information it was using to drive your search. The
+ command doesn't use much space, so it doesn't matter if you
+ forget to run this command. However, <span class="command"><strong>hg bisect</strong></span> won't let you start a new
+ search in that repository until you do a <span class="command"><strong>hg bisect --reset</strong></span>.</p><pre id="id396936" class="screen"><code class="prompt">$</code> <strong class="userinput"><code>hg bisect --reset</code></strong>
+
+</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="id396622">Tips for finding bugs effectively</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396628">Give consistent input</h3></div></div></div><p id="x_14b"><a name="x_14b"></a>The <span class="command"><strong>hg bisect</strong></span> command
+ requires that you correctly report the result of every test
+ you perform. If you tell it that a test failed when it really
+ succeeded, it <span class="emphasis"><em>might</em></span> be able to detect the
+ inconsistency. If it can identify an inconsistency in your
+ reports, it will tell you that a particular changeset is both
+ good and bad. However, it can't do this perfectly; it's about
+ as likely to report the wrong changeset as the source of the
+ bug.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396884">Automate as much as possible</h3></div></div></div><p id="x_14c"><a name="x_14c"></a>When I started using the <span class="command"><strong>hg
+ bisect</strong></span> command, I tried a few times to run my
+ tests by hand, on the command line. This is an approach that
+ I, at least, am not suited to. After a few tries, I found
+ that I was making enough mistakes that I was having to restart
+ my searches several times before finally getting correct
+ results.</p><p id="x_14d"><a name="x_14d"></a>My initial problems with driving the <span class="command"><strong>hg bisect</strong></span> command by hand occurred
+ even with simple searches on small repositories; if the
+ problem you're looking for is more subtle, or the number of
+ tests that <span class="command"><strong>hg bisect</strong></span> must
+ perform increases, the likelihood of operator error ruining
+ the search is much higher. Once I started automating my
+ tests, I had much better results.</p><p id="x_14e"><a name="x_14e"></a>The key to automated testing is twofold:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_14f"><a name="x_14f"></a>always test for the same symptom, and</p></li><li><p id="x_150"><a name="x_150"></a>always feed consistent input to the <span class="command"><strong>hg bisect</strong></span> command.</p></li></ul></div><p id="x_151"><a name="x_151"></a>In my tutorial example above, the <span class="command"><strong>grep</strong></span>
+
+ command tests for the symptom, and the <code class="literal">if</code>
+ statement takes the result of this check and ensures that we
+ always feed the same input to the <span class="command"><strong>hg
+ bisect</strong></span> command. The <code class="literal">mytest</code>
+ function marries these together in a reproducible way, so that
+ every test is uniform and consistent.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396713">Check your results</h3></div></div></div><p id="x_152"><a name="x_152"></a>Because the output of a <span class="command"><strong>hg
+ bisect</strong></span> search is only as good as the input you
+ give it, don't take the changeset it reports as the absolute
+ truth. A simple way to cross-check its report is to manually
+ run your test at each of the following changesets:</p><div class="itemizedlist"><ul type="disc"><li><p id="x_153"><a name="x_153"></a>The changeset that it reports as the first bad
+ revision. Your test should still report this as
+ bad.</p></li><li><p id="x_154"><a name="x_154"></a>The parent of that changeset (either parent,
+ if it's a merge). Your test should report this changeset
+ as good.</p></li><li><p id="x_155"><a name="x_155"></a>A child of that changeset. Your test should
+ report this changeset as bad.</p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396770">Beware interference between bugs</h3></div></div></div><p id="x_156"><a name="x_156"></a>It's possible that your search for one bug could be
+ disrupted by the presence of another. For example, let's say
+ your software crashes at revision 100, and worked correctly at
+ revision 50. Unknown to you, someone else introduced a
+ different crashing bug at revision 60, and fixed it at
+ revision 80. This could distort your results in one of
+ several ways.</p><p id="x_157"><a name="x_157"></a>It is possible that this other bug completely
+ “<span class="quote">masks</span>” yours, which is to say that it occurs
+ before your bug has a chance to manifest itself. If you can't
+ avoid that other bug (for example, it prevents your project
+ from building), and so can't tell whether your bug is present
+ in a particular changeset, the <span class="command"><strong>hg
+ bisect</strong></span> command cannot help you directly. Instead,
+ you can mark a changeset as untested by running <span class="command"><strong>hg bisect --skip</strong></span>.</p><p id="x_158"><a name="x_158"></a>A different problem could arise if your test for a bug's
+ presence is not specific enough. If you check for “<span class="quote">my
+ program crashes</span>”, then both your crashing bug and an
+ unrelated crashing bug that masks it will look like the same
+ thing, and mislead <span class="command"><strong>hg
+ bisect</strong></span>.</p><p id="x_159"><a name="x_159"></a>Another useful situation in which to use <span class="command"><strong>hg bisect --skip</strong></span> is if you can't
+ test a revision because your project was in a broken and hence
+ untestable state at that revision, perhaps because someone
+ checked in a change that prevented the project from
+ building.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title" id="id396856">Bracket your search lazily</h3></div></div></div><p id="x_15a"><a name="x_15a"></a>Choosing the first “<span class="quote">good</span>” and
+ “<span class="quote">bad</span>” changesets that will mark the end points of
+ your search is often easy, but it bears a little discussion
+ nevertheless. From the perspective of <span class="command"><strong>hg bisect</strong></span>, the “<span class="quote">newest</span>”
+ changeset is conventionally “<span class="quote">bad</span>”, and the older
+ changeset is “<span class="quote">good</span>”.</p><p id="x_15b"><a name="x_15b"></a>If you're having trouble remembering when a suitable
+ “<span class="quote">good</span>” change was, so that you can tell <span class="command"><strong>hg bisect</strong></span>, you could do worse than
+ testing changesets at random. Just remember to eliminate
+ contenders that can't possibly exhibit the bug (perhaps
+ because the feature with the bug isn't present yet) and those
+ where another problem masks the bug (as I discussed
+ above).</p><p id="x_15c"><a name="x_15c"></a>Even if you end up “<span class="quote">early</span>” by thousands of
+ changesets or months of history, you will only add a handful
+ of tests to the total number that <span class="command"><strong>hg
+ bisect</strong></span> must perform, thanks to its logarithmic
+ behavior.</p></div></div></div><div class="hgfooter"><p><img src="/support/figs/rss.png"> Want to stay up to date? Subscribe to the comment feed for <a id="chapterfeed" class="feed" href="/feeds/comments/">this chapter</a>, or the <a class="feed" href="/feeds/comments/">entire book</a>.</p><p>Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan.
+ Icons by <a href="mailto:mattahan@gmail.com">Paul Davey</a> aka <a href="http://mattahan.deviantart.com/">Mattahan</a>.</p></div><div class="navfooter"><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="managing-releases-and-branchy-development.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="handling-repository-events-with-hooks.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 8. Managing releases and branchy development </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 10. Handling repository events with hooks</td></tr></table></div><script type="text/javascript">
+ var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+ document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+ </script><script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-1805907-5");
+ pageTracker._trackPageview();
+ } catch(err) {}</script></body></html>
+