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