hgbook

view fr/ch09-undo.xml @ 996:6f8c48362758

merge with trunk
author Romain PELISSE <belaran@gmail.com>
date Sat Sep 12 17:58:56 2009 +0200 (2009-09-12)
parents 6b680d569bb4 f0110009e946
children
line source
1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
3 <chapter id="chap:undo">
4 <?dbhtml filename="finding-and-fixing-mistakes.html"?>
5 <title>Finding and fixing mistakes</title>
7 <para id="x_d2">To err might be human, but to really handle the consequences
8 well takes a top-notch revision control system. In this chapter,
9 we'll discuss some of the techniques you can use when you find
10 that a problem has crept into your project. Mercurial has some
11 highly capable features that will help you to isolate the sources
12 of problems, and to handle them appropriately.</para>
14 <sect1>
15 <title>Erasing local history</title>
17 <sect2>
18 <title>The accidental commit</title>
20 <para id="x_d3">I have the occasional but persistent problem of typing
21 rather more quickly than I can think, which sometimes results
22 in me committing a changeset that is either incomplete or
23 plain wrong. In my case, the usual kind of incomplete
24 changeset is one in which I've created a new source file, but
25 forgotten to <command role="hg-cmd">hg add</command> it. A
26 <quote>plain wrong</quote> changeset is not as common, but no
27 less annoying.</para>
29 </sect2>
30 <sect2 id="sec:undo:rollback">
31 <title>Rolling back a transaction</title>
33 <para id="x_d4">In <xref linkend="sec:concepts:txn"/>, I
34 mentioned that Mercurial treats each modification of a
35 repository as a <emphasis>transaction</emphasis>. Every time
36 you commit a changeset or pull changes from another
37 repository, Mercurial remembers what you did. You can undo,
38 or <emphasis>roll back</emphasis>, exactly one of these
39 actions using the <command role="hg-cmd">hg rollback</command>
40 command. (See <xref linkend="sec:undo:rollback-after-push"/>
41 for an important caveat about the use of this command.)</para>
43 <para id="x_d5">Here's a mistake that I often find myself making:
44 committing a change in which I've created a new file, but
45 forgotten to <command role="hg-cmd">hg add</command>
46 it.</para>
48 &interaction.rollback.commit;
50 <para id="x_d6">Looking at the output of <command role="hg-cmd">hg
51 status</command> after the commit immediately confirms the
52 error.</para>
54 &interaction.rollback.status;
56 <para id="x_d7">The commit captured the changes to the file
57 <filename>a</filename>, but not the new file
58 <filename>b</filename>. If I were to push this changeset to a
59 repository that I shared with a colleague, the chances are
60 high that something in <filename>a</filename> would refer to
61 <filename>b</filename>, which would not be present in their
62 repository when they pulled my changes. I would thus become
63 the object of some indignation.</para>
65 <para id="x_d8">However, luck is with me&emdash;I've caught my error
66 before I pushed the changeset. I use the <command
67 role="hg-cmd">hg rollback</command> command, and Mercurial
68 makes that last changeset vanish.</para>
70 &interaction.rollback.rollback;
72 <para id="x_d9">Notice that the changeset is no longer present in the
73 repository's history, and the working directory once again
74 thinks that the file <filename>a</filename> is modified. The
75 commit and rollback have left the working directory exactly as
76 it was prior to the commit; the changeset has been completely
77 erased. I can now safely <command role="hg-cmd">hg
78 add</command> the file <filename>b</filename>, and rerun my
79 commit.</para>
81 &interaction.rollback.add;
83 </sect2>
84 <sect2>
85 <title>The erroneous pull</title>
87 <para id="x_da">It's common practice with Mercurial to maintain separate
88 development branches of a project in different repositories.
89 Your development team might have one shared repository for
90 your project's <quote>0.9</quote> release, and another,
91 containing different changes, for the <quote>1.0</quote>
92 release.</para>
94 <para id="x_db">Given this, you can imagine that the consequences could be
95 messy if you had a local <quote>0.9</quote> repository, and
96 accidentally pulled changes from the shared <quote>1.0</quote>
97 repository into it. At worst, you could be paying
98 insufficient attention, and push those changes into the shared
99 <quote>0.9</quote> tree, confusing your entire team (but don't
100 worry, we'll return to this horror scenario later). However,
101 it's more likely that you'll notice immediately, because
102 Mercurial will display the URL it's pulling from, or you will
103 see it pull a suspiciously large number of changes into the
104 repository.</para>
106 <para id="x_dc">The <command role="hg-cmd">hg rollback</command> command
107 will work nicely to expunge all of the changesets that you
108 just pulled. Mercurial groups all changes from one <command
109 role="hg-cmd">hg pull</command> into a single transaction,
110 so one <command role="hg-cmd">hg rollback</command> is all you
111 need to undo this mistake.</para>
113 </sect2>
114 <sect2 id="sec:undo:rollback-after-push">
115 <title>Rolling back is useless once you've pushed</title>
117 <para id="x_dd">The value of the <command role="hg-cmd">hg
118 rollback</command> command drops to zero once you've pushed
119 your changes to another repository. Rolling back a change
120 makes it disappear entirely, but <emphasis>only</emphasis> in
121 the repository in which you perform the <command
122 role="hg-cmd">hg rollback</command>. Because a rollback
123 eliminates history, there's no way for the disappearance of a
124 change to propagate between repositories.</para>
126 <para id="x_de">If you've pushed a change to another
127 repository&emdash;particularly if it's a shared
128 repository&emdash;it has essentially <quote>escaped into the
129 wild,</quote> and you'll have to recover from your mistake
130 in a different way. If you push a changeset somewhere, then
131 roll it back, then pull from the repository you pushed to, the
132 changeset you thought you'd gotten rid of will simply reappear
133 in your repository.</para>
135 <para id="x_df">(If you absolutely know for sure that the change
136 you want to roll back is the most recent change in the
137 repository that you pushed to, <emphasis>and</emphasis> you
138 know that nobody else could have pulled it from that
139 repository, you can roll back the changeset there, too, but
140 you really should not expect this to work reliably. Sooner or
141 later a change really will make it into a repository that you
142 don't directly control (or have forgotten about), and come
143 back to bite you.)</para>
145 </sect2>
146 <sect2>
147 <title>You can only roll back once</title>
149 <para id="x_e0">Mercurial stores exactly one transaction in its
150 transaction log; that transaction is the most recent one that
151 occurred in the repository. This means that you can only roll
152 back one transaction. If you expect to be able to roll back
153 one transaction, then its predecessor, this is not the
154 behavior you will get.</para>
156 &interaction.rollback.twice;
158 <para id="x_e1">Once you've rolled back one transaction in a repository,
159 you can't roll back again in that repository until you perform
160 another commit or pull.</para>
162 </sect2>
163 </sect1>
164 <sect1>
165 <title>Reverting the mistaken change</title>
167 <para id="x_e2">If you make a modification to a file, and decide that you
168 really didn't want to change the file at all, and you haven't
169 yet committed your changes, the <command role="hg-cmd">hg
170 revert</command> command is the one you'll need. It looks at
171 the changeset that's the parent of the working directory, and
172 restores the contents of the file to their state as of that
173 changeset. (That's a long-winded way of saying that, in the
174 normal case, it undoes your modifications.)</para>
176 <para id="x_e3">Let's illustrate how the <command role="hg-cmd">hg
177 revert</command> command works with yet another small example.
178 We'll begin by modifying a file that Mercurial is already
179 tracking.</para>
181 &interaction.daily.revert.modify;
183 <para id="x_e4">If we don't
184 want that change, we can simply <command role="hg-cmd">hg
185 revert</command> the file.</para>
187 &interaction.daily.revert.unmodify;
189 <para id="x_e5">The <command role="hg-cmd">hg revert</command> command
190 provides us with an extra degree of safety by saving our
191 modified file with a <filename>.orig</filename>
192 extension.</para>
194 &interaction.daily.revert.status;
196 <tip>
197 <title>Be careful with <filename>.orig</filename> files</title>
199 <para id="x_6b8">It's extremely unlikely that you are either using
200 Mercurial to manage files with <filename>.orig</filename>
201 extensions or that you even care about the contents of such
202 files. Just in case, though, it's useful to remember that
203 <command role="hg-cmd">hg revert</command> will
204 unconditionally overwrite an existing file with a
205 <filename>.orig</filename> extension. For instance, if you
206 already have a file named <filename>foo.orig</filename> when
207 you revert <filename>foo</filename>, the contents of
208 <filename>foo.orig</filename> will be clobbered.</para>
209 </tip>
211 <para id="x_e6">Here is a summary of the cases that the <command
212 role="hg-cmd">hg revert</command> command can deal with. We
213 will describe each of these in more detail in the section that
214 follows.</para>
215 <itemizedlist>
216 <listitem><para id="x_e7">If you modify a file, it will restore the file
217 to its unmodified state.</para>
218 </listitem>
219 <listitem><para id="x_e8">If you <command role="hg-cmd">hg add</command> a
220 file, it will undo the <quote>added</quote> state of the
221 file, but leave the file itself untouched.</para>
222 </listitem>
223 <listitem><para id="x_e9">If you delete a file without telling Mercurial,
224 it will restore the file to its unmodified contents.</para>
225 </listitem>
226 <listitem><para id="x_ea">If you use the <command role="hg-cmd">hg
227 remove</command> command to remove a file, it will undo
228 the <quote>removed</quote> state of the file, and restore
229 the file to its unmodified contents.</para>
230 </listitem></itemizedlist>
232 <sect2 id="sec:undo:mgmt">
233 <title>File management errors</title>
235 <para id="x_eb">The <command role="hg-cmd">hg revert</command> command is
236 useful for more than just modified files. It lets you reverse
237 the results of all of Mercurial's file management
238 commands&emdash;<command role="hg-cmd">hg add</command>,
239 <command role="hg-cmd">hg remove</command>, and so on.</para>
241 <para id="x_ec">If you <command role="hg-cmd">hg add</command> a file,
242 then decide that in fact you don't want Mercurial to track it,
243 use <command role="hg-cmd">hg revert</command> to undo the
244 add. Don't worry; Mercurial will not modify the file in any
245 way. It will just <quote>unmark</quote> the file.</para>
247 &interaction.daily.revert.add;
249 <para id="x_ed">Similarly, if you ask Mercurial to <command
250 role="hg-cmd">hg remove</command> a file, you can use
251 <command role="hg-cmd">hg revert</command> to restore it to
252 the contents it had as of the parent of the working directory.
253 &interaction.daily.revert.remove; This works just as
254 well for a file that you deleted by hand, without telling
255 Mercurial (recall that in Mercurial terminology, this kind of
256 file is called <quote>missing</quote>).</para>
258 &interaction.daily.revert.missing;
260 <para id="x_ee">If you revert a <command role="hg-cmd">hg copy</command>,
261 the copied-to file remains in your working directory
262 afterwards, untracked. Since a copy doesn't affect the
263 copied-from file in any way, Mercurial doesn't do anything
264 with the copied-from file.</para>
266 &interaction.daily.revert.copy;
267 </sect2>
268 </sect1>
270 <sect1>
271 <title>Dealing with committed changes</title>
273 <para id="x_f5">Consider a case where you have committed a change
274 <emphasis>a</emphasis>, and another change
275 <emphasis>b</emphasis> on top of it; you then realise that
276 change <emphasis>a</emphasis> was incorrect. Mercurial lets you
277 <quote>back out</quote> an entire changeset automatically, and
278 building blocks that let you reverse part of a changeset by
279 hand.</para>
281 <para id="x_f6">Before you read this section, here's something to
282 keep in mind: the <command role="hg-cmd">hg backout</command>
283 command undoes the effect of a change by
284 <emphasis>adding</emphasis> to your repository's history, not by
285 modifying or erasing it. It's the right tool to use if you're
286 fixing bugs, but not if you're trying to undo some change that
287 has catastrophic consequences. To deal with those, see
288 <xref linkend="sec:undo:aaaiiieee"/>.</para>
290 <sect2>
291 <title>Backing out a changeset</title>
293 <para id="x_f7">The <command role="hg-cmd">hg backout</command> command
294 lets you <quote>undo</quote> the effects of an entire
295 changeset in an automated fashion. Because Mercurial's
296 history is immutable, this command <emphasis>does
297 not</emphasis> get rid of the changeset you want to undo.
298 Instead, it creates a new changeset that
299 <emphasis>reverses</emphasis> the effect of the to-be-undone
300 changeset.</para>
302 <para id="x_f8">The operation of the <command role="hg-cmd">hg
303 backout</command> command is a little intricate, so let's
304 illustrate it with some examples. First, we'll create a
305 repository with some simple changes.</para>
307 &interaction.backout.init;
309 <para id="x_f9">The <command role="hg-cmd">hg backout</command> command
310 takes a single changeset ID as its argument; this is the
311 changeset to back out. Normally, <command role="hg-cmd">hg
312 backout</command> will drop you into a text editor to write
313 a commit message, so you can record why you're backing the
314 change out. In this example, we provide a commit message on
315 the command line using the <option
316 role="hg-opt-backout">-m</option> option.</para>
318 </sect2>
319 <sect2>
320 <title>Backing out the tip changeset</title>
322 <para id="x_fa">We're going to start by backing out the last changeset we
323 committed.</para>
325 &interaction.backout.simple;
327 <para id="x_fb">You can see that the second line from
328 <filename>myfile</filename> is no longer present. Taking a
329 look at the output of <command role="hg-cmd">hg log</command>
330 gives us an idea of what the <command role="hg-cmd">hg
331 backout</command> command has done.
332 &interaction.backout.simple.log; Notice that the new changeset
333 that <command role="hg-cmd">hg backout</command> has created
334 is a child of the changeset we backed out. It's easier to see
335 this in <xref linkend="fig:undo:backout"/>, which presents a
336 graphical view of the change history. As you can see, the
337 history is nice and linear.</para>
339 <figure id="fig:undo:backout">
340 <title>Backing out a change using the <command
341 role="hg-cmd">hg backout</command> command</title>
342 <mediaobject>
343 <imageobject><imagedata fileref="figs/undo-simple.png"/></imageobject>
344 <textobject><phrase>XXX add text</phrase></textobject>
345 </mediaobject>
346 </figure>
348 </sect2>
349 <sect2>
350 <title>Backing out a non-tip change</title>
352 <para id="x_fd">If you want to back out a change other than the last one
353 you committed, pass the <option
354 role="hg-opt-backout">--merge</option> option to the
355 <command role="hg-cmd">hg backout</command> command.</para>
357 &interaction.backout.non-tip.clone;
359 <para id="x_fe">This makes backing out any changeset a
360 <quote>one-shot</quote> operation that's usually simple and
361 fast.</para>
363 &interaction.backout.non-tip.backout;
365 <para id="x_ff">If you take a look at the contents of
366 <filename>myfile</filename> after the backout finishes, you'll
367 see that the first and third changes are present, but not the
368 second.</para>
370 &interaction.backout.non-tip.cat;
372 <para id="x_100">As the graphical history in <xref
373 linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial
374 still commits one change in this kind of situation (the
375 box-shaped node is the ones that Mercurial commits
376 automatically), but the revision graph now looks different.
377 Before Mercurial begins the backout process, it first
378 remembers what the current parent of the working directory is.
379 It then backs out the target changeset, and commits that as a
380 changeset. Finally, it merges back to the previous parent of
381 the working directory, but notice that it <emphasis>does not
382 commit</emphasis> the result of the merge. The repository
383 now contains two heads, and the working directory is in a
384 merge state.</para>
386 <figure id="fig:undo:backout-non-tip">
387 <title>Automated backout of a non-tip change using the
388 <command role="hg-cmd">hg backout</command> command</title>
389 <mediaobject>
390 <imageobject><imagedata fileref="figs/undo-non-tip.png"/></imageobject>
391 <textobject><phrase>XXX add text</phrase></textobject>
392 </mediaobject>
393 </figure>
395 <para id="x_103">The result is that you end up <quote>back where you
396 were</quote>, only with some extra history that undoes the
397 effect of the changeset you wanted to back out.</para>
399 <para id="x_6b9">You might wonder why Mercurial does not commit the result
400 of the merge that it performed. The reason lies in Mercurial
401 behaving conservatively: a merge naturally has more scope for
402 error than simply undoing the effect of the tip changeset,
403 so your work will be safest if you first inspect (and test!)
404 the result of the merge, <emphasis>then</emphasis> commit
405 it.</para>
407 <sect3>
408 <title>Always use the <option
409 role="hg-opt-backout">--merge</option> option</title>
411 <para id="x_104">In fact, since the <option
412 role="hg-opt-backout">--merge</option> option will do the
413 <quote>right thing</quote> whether or not the changeset
414 you're backing out is the tip (i.e. it won't try to merge if
415 it's backing out the tip, since there's no need), you should
416 <emphasis>always</emphasis> use this option when you run the
417 <command role="hg-cmd">hg backout</command> command.</para>
419 </sect3>
420 </sect2>
421 <sect2>
422 <title>Gaining more control of the backout process</title>
424 <para id="x_105">While I've recommended that you always use the <option
425 role="hg-opt-backout">--merge</option> option when backing
426 out a change, the <command role="hg-cmd">hg backout</command>
427 command lets you decide how to merge a backout changeset.
428 Taking control of the backout process by hand is something you
429 will rarely need to do, but it can be useful to understand
430 what the <command role="hg-cmd">hg backout</command> command
431 is doing for you automatically. To illustrate this, let's
432 clone our first repository, but omit the backout change that
433 it contains.</para>
435 &interaction.backout.manual.clone;
437 <para id="x_106">As with our
438 earlier example, We'll commit a third changeset, then back out
439 its parent, and see what happens.</para>
441 &interaction.backout.manual.backout;
443 <para id="x_107">Our new changeset is again a descendant of the changeset
444 we backout out; it's thus a new head, <emphasis>not</emphasis>
445 a descendant of the changeset that was the tip. The <command
446 role="hg-cmd">hg backout</command> command was quite
447 explicit in telling us this.</para>
449 &interaction.backout.manual.log;
451 <para id="x_108">Again, it's easier to see what has happened by looking at
452 a graph of the revision history, in <xref
453 linkend="fig:undo:backout-manual"/>. This makes it clear
454 that when we use <command role="hg-cmd">hg backout</command>
455 to back out a change other than the tip, Mercurial adds a new
456 head to the repository (the change it committed is
457 box-shaped).</para>
459 <figure id="fig:undo:backout-manual">
460 <title>Backing out a change using the <command
461 role="hg-cmd">hg backout</command> command</title>
462 <mediaobject>
463 <imageobject><imagedata fileref="figs/undo-manual.png"/></imageobject>
464 <textobject><phrase>XXX add text</phrase></textobject>
465 </mediaobject>
466 </figure>
468 <para id="x_10a">After the <command role="hg-cmd">hg backout</command>
469 command has completed, it leaves the new
470 <quote>backout</quote> changeset as the parent of the working
471 directory.</para>
473 &interaction.backout.manual.parents;
475 <para id="x_10b">Now we have two isolated sets of changes.</para>
477 &interaction.backout.manual.heads;
479 <para id="x_10c">Let's think about what we expect to see as the contents of
480 <filename>myfile</filename> now. The first change should be
481 present, because we've never backed it out. The second change
482 should be missing, as that's the change we backed out. Since
483 the history graph shows the third change as a separate head,
484 we <emphasis>don't</emphasis> expect to see the third change
485 present in <filename>myfile</filename>.</para>
487 &interaction.backout.manual.cat;
489 <para id="x_10d">To get the third change back into the file, we just do a
490 normal merge of our two heads.</para>
492 &interaction.backout.manual.merge;
494 <para id="x_10e">Afterwards, the graphical history of our
495 repository looks like
496 <xref linkend="fig:undo:backout-manual-merge"/>.</para>
498 <figure id="fig:undo:backout-manual-merge">
499 <title>Manually merging a backout change</title>
500 <mediaobject>
501 <imageobject><imagedata fileref="figs/undo-manual-merge.png"/></imageobject>
502 <textobject><phrase>XXX add text</phrase></textobject>
503 </mediaobject>
504 </figure>
506 </sect2>
507 <sect2>
508 <title>Why <command role="hg-cmd">hg backout</command> works as
509 it does</title>
511 <para id="x_110">Here's a brief description of how the <command
512 role="hg-cmd">hg backout</command> command works.</para>
513 <orderedlist>
514 <listitem><para id="x_111">It ensures that the working directory is
515 <quote>clean</quote>, i.e. that the output of <command
516 role="hg-cmd">hg status</command> would be empty.</para>
517 </listitem>
518 <listitem><para id="x_112">It remembers the current parent of the working
519 directory. Let's call this changeset
520 <literal>orig</literal>.</para>
521 </listitem>
522 <listitem><para id="x_113">It does the equivalent of a <command
523 role="hg-cmd">hg update</command> to sync the working
524 directory to the changeset you want to back out. Let's
525 call this changeset <literal>backout</literal>.</para>
526 </listitem>
527 <listitem><para id="x_114">It finds the parent of that changeset. Let's
528 call that changeset <literal>parent</literal>.</para>
529 </listitem>
530 <listitem><para id="x_115">For each file that the
531 <literal>backout</literal> changeset affected, it does the
532 equivalent of a <command role="hg-cmd">hg revert -r
533 parent</command> on that file, to restore it to the
534 contents it had before that changeset was
535 committed.</para>
536 </listitem>
537 <listitem><para id="x_116">It commits the result as a new changeset.
538 This changeset has <literal>backout</literal> as its
539 parent.</para>
540 </listitem>
541 <listitem><para id="x_117">If you specify <option
542 role="hg-opt-backout">--merge</option> on the command
543 line, it merges with <literal>orig</literal>, and commits
544 the result of the merge.</para>
545 </listitem></orderedlist>
547 <para id="x_118">An alternative way to implement the <command
548 role="hg-cmd">hg backout</command> command would be to
549 <command role="hg-cmd">hg export</command> the
550 to-be-backed-out changeset as a diff, then use the <option
551 role="cmd-opt-patch">--reverse</option> option to the
552 <command>patch</command> command to reverse the effect of the
553 change without fiddling with the working directory. This
554 sounds much simpler, but it would not work nearly as
555 well.</para>
557 <para id="x_119">The reason that <command role="hg-cmd">hg
558 backout</command> does an update, a commit, a merge, and
559 another commit is to give the merge machinery the best chance
560 to do a good job when dealing with all the changes
561 <emphasis>between</emphasis> the change you're backing out and
562 the current tip.</para>
564 <para id="x_11a">If you're backing out a changeset that's 100 revisions
565 back in your project's history, the chances that the
566 <command>patch</command> command will be able to apply a
567 reverse diff cleanly are not good, because intervening changes
568 are likely to have <quote>broken the context</quote> that
569 <command>patch</command> uses to determine whether it can
570 apply a patch (if this sounds like gibberish, see <xref
571 linkend="sec:mq:patch"/> for a
572 discussion of the <command>patch</command> command). Also,
573 Mercurial's merge machinery will handle files and directories
574 being renamed, permission changes, and modifications to binary
575 files, none of which <command>patch</command> can deal
576 with.</para>
578 </sect2>
579 </sect1>
580 <sect1 id="sec:undo:aaaiiieee">
581 <title>Changes that should never have been</title>
583 <para id="x_11b">Most of the time, the <command role="hg-cmd">hg
584 backout</command> command is exactly what you need if you want
585 to undo the effects of a change. It leaves a permanent record
586 of exactly what you did, both when committing the original
587 changeset and when you cleaned up after it.</para>
589 <para id="x_11c">On rare occasions, though, you may find that you've
590 committed a change that really should not be present in the
591 repository at all. For example, it would be very unusual, and
592 usually considered a mistake, to commit a software project's
593 object files as well as its source files. Object files have
594 almost no intrinsic value, and they're <emphasis>big</emphasis>,
595 so they increase the size of the repository and the amount of
596 time it takes to clone or pull changes.</para>
598 <para id="x_11d">Before I discuss the options that you have if you commit a
599 <quote>brown paper bag</quote> change (the kind that's so bad
600 that you want to pull a brown paper bag over your head), let me
601 first discuss some approaches that probably won't work.</para>
603 <para id="x_11e">Since Mercurial treats history as
604 accumulative&emdash;every change builds on top of all changes
605 that preceded it&emdash;you generally can't just make disastrous
606 changes disappear. The one exception is when you've just
607 committed a change, and it hasn't been pushed or pulled into
608 another repository. That's when you can safely use the <command
609 role="hg-cmd">hg rollback</command> command, as I detailed in
610 <xref linkend="sec:undo:rollback"/>.</para>
612 <para id="x_11f">After you've pushed a bad change to another repository, you
613 <emphasis>could</emphasis> still use <command role="hg-cmd">hg
614 rollback</command> to make your local copy of the change
615 disappear, but it won't have the consequences you want. The
616 change will still be present in the remote repository, so it
617 will reappear in your local repository the next time you
618 pull.</para>
620 <para id="x_120">If a situation like this arises, and you know which
621 repositories your bad change has propagated into, you can
622 <emphasis>try</emphasis> to get rid of the change from
623 <emphasis>every</emphasis> one of those repositories. This is,
624 of course, not a satisfactory solution: if you miss even a
625 single repository while you're expunging, the change is still
626 <quote>in the wild</quote>, and could propagate further.</para>
628 <para id="x_121">If you've committed one or more changes
629 <emphasis>after</emphasis> the change that you'd like to see
630 disappear, your options are further reduced. Mercurial doesn't
631 provide a way to <quote>punch a hole</quote> in history, leaving
632 changesets intact.</para>
634 <sect2>
635 <title>Backing out a merge</title>
637 <para id="x_6ba">Since merges are often complicated, it is not unheard of
638 for a merge to be mangled badly, but committed erroneously.
639 Mercurial provides an important safeguard against bad merges
640 by refusing to commit unresolved files, but human ingenuity
641 guarantees that it is still possible to mess a merge up and
642 commit it.</para>
644 <para id="x_6bb">Given a bad merge that has been committed, usually the
645 best way to approach it is to simply try to repair the damage
646 by hand. A complete disaster that cannot be easily fixed up
647 by hand ought to be very rare, but the <command
648 role="hg-cmd">hg backout</command> command may help in
649 making the cleanup easier. It offers a <option
650 role="hg-opt-backout">--parent</option> option, which lets
651 you specify which parent to revert to when backing out a
652 merge.</para>
654 <figure id="fig:undo:bad-merge-1">
655 <title>A bad merge</title>
656 <mediaobject>
657 <imageobject><imagedata fileref="figs/bad-merge-1.png"/></imageobject>
658 <textobject><phrase>XXX add text</phrase></textobject>
659 </mediaobject>
660 </figure>
662 <para id="x_6bc">Suppose we have a revision graph like that in <xref
663 linkend="fig:undo:bad-merge-1"/>. What we'd like is to
664 <emphasis>redo</emphasis> the merge of revisions 2 and
665 3.</para>
667 <para id="x_6bd">One way to do so would be as follows.</para>
669 <orderedlist>
670 <listitem>
671 <para id="x_6be">Call <command role="hg-cmd">hg backout --rev=4
672 --parent=2</command>. This tells <command
673 role="hg-cmd">hg backout</command> to back out revision
674 4, which is the bad merge, and to when deciding which
675 revision to prefer, to choose parent 2, one of the parents
676 of the merge. The effect can be seen in <xref
677 linkend="fig:undo:bad-merge-2"/>.</para>
678 <figure id="fig:undo:bad-merge-2">
679 <title>Backing out the merge, favoring one parent</title>
680 <mediaobject>
681 <imageobject><imagedata fileref="figs/bad-merge-2.png"/></imageobject>
682 <textobject><phrase>XXX add text</phrase></textobject>
683 </mediaobject>
684 </figure>
685 </listitem>
687 <listitem>
688 <para id="x_6bf">Call <command role="hg-cmd">hg backout --rev=4
689 --parent=3</command>. This tells <command
690 role="hg-cmd">hg backout</command> to back out revision
691 4 again, but this time to choose parent 3, the other
692 parent of the merge. The result is visible in <xref
693 linkend="fig:undo:bad-merge-3"/>, in which the repository
694 now contains three heads.</para>
695 <figure id="fig:undo:bad-merge-3">
696 <title>Backing out the merge, favoring the other
697 parent</title>
698 <mediaobject>
699 <imageobject><imagedata fileref="figs/bad-merge-3.png"/></imageobject>
700 <textobject><phrase>XXX add text</phrase></textobject>
701 </mediaobject>
702 </figure>
703 </listitem>
705 <listitem>
706 <para id="x_6c0">Redo the bad merge by merging the two backout heads,
707 which reduces the number of heads in the repository to
708 two, as can be seen in <xref
709 linkend="fig:undo:bad-merge-4"/>.</para>
710 <figure id="fig:undo:bad-merge-4">
711 <title>Merging the backouts</title>
712 <mediaobject>
713 <imageobject><imagedata fileref="figs/bad-merge-4.png"/></imageobject>
714 <textobject><phrase>XXX add text</phrase></textobject>
715 </mediaobject>
716 </figure>
717 </listitem>
719 <listitem>
720 <para id="x_6c1">Merge with the commit that was made after the bad
721 merge, as shown in <xref
722 linkend="fig:undo:bad-merge-5"/>.</para>
723 <figure id="fig:undo:bad-merge-5">
724 <title>Merging the backouts</title>
725 <mediaobject>
726 <imageobject><imagedata fileref="figs/bad-merge-5.png"/></imageobject>
727 <textobject><phrase>XXX add text</phrase></textobject>
728 </mediaobject>
729 </figure>
730 </listitem>
731 </orderedlist>
732 </sect2>
734 <sect2>
735 <title>Protect yourself from <quote>escaped</quote>
736 changes</title>
738 <para id="x_123">If you've committed some changes to your local repository
739 and they've been pushed or pulled somewhere else, this isn't
740 necessarily a disaster. You can protect yourself ahead of
741 time against some classes of bad changeset. This is
742 particularly easy if your team usually pulls changes from a
743 central repository.</para>
745 <para id="x_124">By configuring some hooks on that repository to validate
746 incoming changesets (see chapter <xref linkend="chap:hook"/>),
747 you can
748 automatically prevent some kinds of bad changeset from being
749 pushed to the central repository at all. With such a
750 configuration in place, some kinds of bad changeset will
751 naturally tend to <quote>die out</quote> because they can't
752 propagate into the central repository. Better yet, this
753 happens without any need for explicit intervention.</para>
755 <para id="x_125">For instance, an incoming change hook that
756 verifies that a changeset will actually compile can prevent
757 people from inadvertently <quote>breaking the
758 build</quote>.</para>
759 </sect2>
761 <sect2>
762 <title>What to do about sensitive changes that escape</title>
764 <para id="x_6c2">Even a carefully run project can suffer an unfortunate
765 event such as the committing and uncontrolled propagation of a
766 file that contains important passwords.</para>
768 <para id="x_6c3">If something like this happens to you, and the information
769 that gets accidentally propagated is truly sensitive, your
770 first step should be to mitigate the effect of the leak
771 without trying to control the leak itself. If you are not 100%
772 certain that you know exactly who could have seen the changes,
773 you should immediately change passwords, cancel credit cards,
774 or find some other way to make sure that the information that
775 has leaked is no longer useful. In other words, assume that
776 the change has propagated far and wide, and that there's
777 nothing more you can do.</para>
779 <para id="x_6c4">You might hope that there would be mechanisms you could
780 use to either figure out who has seen a change or to erase the
781 change permanently everywhere, but there are good reasons why
782 these are not possible.</para>
784 <para id="x_6c5">Mercurial does not provide an audit trail of who has
785 pulled changes from a repository, because it is usually either
786 impossible to record such information or trivial to spoof it.
787 In a multi-user or networked environment, you should thus be
788 extremely skeptical of yourself if you think that you have
789 identified every place that a sensitive changeset has
790 propagated to. Don't forget that people can and will send
791 bundles by email, have their backup software save data
792 offsite, carry repositories on USB sticks, and find other
793 completely innocent ways to confound your attempts to track
794 down every copy of a problematic change.</para>
796 <para id="x_6c6">Mercurial also does not provide a way to make a file or
797 changeset completely disappear from history, because there is
798 no way to enforce its disappearance; someone could easily
799 modify their copy of Mercurial to ignore such directives. In
800 addition, even if Mercurial provided such a capability,
801 someone who simply hadn't pulled a <quote>make this file
802 disappear</quote> changeset wouldn't be affected by it, nor
803 would web crawlers visiting at the wrong time, disk backups,
804 or other mechanisms. Indeed, no distributed revision control
805 system can make data reliably vanish. Providing the illusion
806 of such control could easily give a false sense of security,
807 and be worse than not providing it at all.</para>
808 </sect2>
809 </sect1>
811 <sect1 id="sec:undo:bisect">
812 <title>Finding the source of a bug</title>
814 <para id="x_126">While it's all very well to be able to back out a changeset
815 that introduced a bug, this requires that you know which
816 changeset to back out. Mercurial provides an invaluable
817 command, called <command role="hg-cmd">hg bisect</command>, that
818 helps you to automate this process and accomplish it very
819 efficiently.</para>
821 <para id="x_127">The idea behind the <command role="hg-cmd">hg
822 bisect</command> command is that a changeset has introduced
823 some change of behavior that you can identify with a simple
824 pass/fail test. You don't know which piece of code introduced the
825 change, but you know how to test for the presence of the bug.
826 The <command role="hg-cmd">hg bisect</command> command uses your
827 test to direct its search for the changeset that introduced the
828 code that caused the bug.</para>
830 <para id="x_128">Here are a few scenarios to help you understand how you
831 might apply this command.</para>
832 <itemizedlist>
833 <listitem><para id="x_129">The most recent version of your software has a
834 bug that you remember wasn't present a few weeks ago, but
835 you don't know when it was introduced. Here, your binary
836 test checks for the presence of that bug.</para>
837 </listitem>
838 <listitem><para id="x_12a">You fixed a bug in a rush, and now it's time to
839 close the entry in your team's bug database. The bug
840 database requires a changeset ID when you close an entry,
841 but you don't remember which changeset you fixed the bug in.
842 Once again, your binary test checks for the presence of the
843 bug.</para>
844 </listitem>
845 <listitem><para id="x_12b">Your software works correctly, but runs 15%
846 slower than the last time you measured it. You want to know
847 which changeset introduced the performance regression. In
848 this case, your binary test measures the performance of your
849 software, to see whether it's <quote>fast</quote> or
850 <quote>slow</quote>.</para>
851 </listitem>
852 <listitem><para id="x_12c">The sizes of the components of your project that
853 you ship exploded recently, and you suspect that something
854 changed in the way you build your project.</para>
855 </listitem></itemizedlist>
857 <para id="x_12d">From these examples, it should be clear that the <command
858 role="hg-cmd">hg bisect</command> command is not useful only
859 for finding the sources of bugs. You can use it to find any
860 <quote>emergent property</quote> of a repository (anything that
861 you can't find from a simple text search of the files in the
862 tree) for which you can write a binary test.</para>
864 <para id="x_12e">We'll introduce a little bit of terminology here, just to
865 make it clear which parts of the search process are your
866 responsibility, and which are Mercurial's. A
867 <emphasis>test</emphasis> is something that
868 <emphasis>you</emphasis> run when <command role="hg-cmd">hg
869 bisect</command> chooses a changeset. A
870 <emphasis>probe</emphasis> is what <command role="hg-cmd">hg
871 bisect</command> runs to tell whether a revision is good.
872 Finally, we'll use the word <quote>bisect</quote>, as both a
873 noun and a verb, to stand in for the phrase <quote>search using
874 the <command role="hg-cmd">hg bisect</command>
875 command</quote>.</para>
877 <para id="x_12f">One simple way to automate the searching process would be
878 simply to probe every changeset. However, this scales poorly.
879 If it took ten minutes to test a single changeset, and you had
880 10,000 changesets in your repository, the exhaustive approach
881 would take on average 35 <emphasis>days</emphasis> to find the
882 changeset that introduced a bug. Even if you knew that the bug
883 was introduced by one of the last 500 changesets, and limited
884 your search to those, you'd still be looking at over 40 hours to
885 find the changeset that introduced your bug.</para>
887 <para id="x_130">What the <command role="hg-cmd">hg bisect</command> command
888 does is use its knowledge of the <quote>shape</quote> of your
889 project's revision history to perform a search in time
890 proportional to the <emphasis>logarithm</emphasis> of the number
891 of changesets to check (the kind of search it performs is called
892 a dichotomic search). With this approach, searching through
893 10,000 changesets will take less than three hours, even at ten
894 minutes per test (the search will require about 14 tests).
895 Limit your search to the last hundred changesets, and it will
896 take only about an hour (roughly seven tests).</para>
898 <para id="x_131">The <command role="hg-cmd">hg bisect</command> command is
899 aware of the <quote>branchy</quote> nature of a Mercurial
900 project's revision history, so it has no problems dealing with
901 branches, merges, or multiple heads in a repository. It can
902 prune entire branches of history with a single probe, which is
903 how it operates so efficiently.</para>
905 <sect2>
906 <title>Using the <command role="hg-cmd">hg bisect</command>
907 command</title>
909 <para id="x_132">Here's an example of <command role="hg-cmd">hg
910 bisect</command> in action.</para>
912 <note>
913 <para id="x_133"> In versions 0.9.5 and earlier of Mercurial, <command
914 role="hg-cmd">hg bisect</command> was not a core command:
915 it was distributed with Mercurial as an extension. This
916 section describes the built-in command, not the old
917 extension.</para>
918 </note>
920 <para id="x_134">Now let's create a repository, so that we can try out the
921 <command role="hg-cmd">hg bisect</command> command in
922 isolation.</para>
924 &interaction.bisect.init;
926 <para id="x_135">We'll simulate a project that has a bug in it in a
927 simple-minded way: create trivial changes in a loop, and
928 nominate one specific change that will have the
929 <quote>bug</quote>. This loop creates 35 changesets, each
930 adding a single file to the repository. We'll represent our
931 <quote>bug</quote> with a file that contains the text <quote>i
932 have a gub</quote>.</para>
934 &interaction.bisect.commits;
936 <para id="x_136">The next thing that we'd like to do is figure out how to
937 use the <command role="hg-cmd">hg bisect</command> command.
938 We can use Mercurial's normal built-in help mechanism for
939 this.</para>
941 &interaction.bisect.help;
943 <para id="x_137">The <command role="hg-cmd">hg bisect</command> command
944 works in steps. Each step proceeds as follows.</para>
945 <orderedlist>
946 <listitem><para id="x_138">You run your binary test.</para>
947 <itemizedlist>
948 <listitem><para id="x_139">If the test succeeded, you tell <command
949 role="hg-cmd">hg bisect</command> by running the
950 <command role="hg-cmd">hg bisect --good</command>
951 command.</para>
952 </listitem>
953 <listitem><para id="x_13a">If it failed, run the <command
954 role="hg-cmd">hg bisect --bad</command>
955 command.</para></listitem></itemizedlist>
956 </listitem>
957 <listitem><para id="x_13b">The command uses your information to decide
958 which changeset to test next.</para>
959 </listitem>
960 <listitem><para id="x_13c">It updates the working directory to that
961 changeset, and the process begins again.</para>
962 </listitem></orderedlist>
963 <para id="x_13d">The process ends when <command role="hg-cmd">hg
964 bisect</command> identifies a unique changeset that marks
965 the point where your test transitioned from
966 <quote>succeeding</quote> to <quote>failing</quote>.</para>
968 <para id="x_13e">To start the search, we must run the <command
969 role="hg-cmd">hg bisect --reset</command> command.</para>
971 &interaction.bisect.search.init;
973 <para id="x_13f">In our case, the binary test we use is simple: we check to
974 see if any file in the repository contains the string <quote>i
975 have a gub</quote>. If it does, this changeset contains the
976 change that <quote>caused the bug</quote>. By convention, a
977 changeset that has the property we're searching for is
978 <quote>bad</quote>, while one that doesn't is
979 <quote>good</quote>.</para>
981 <para id="x_140">Most of the time, the revision to which the working
982 directory is synced (usually the tip) already exhibits the
983 problem introduced by the buggy change, so we'll mark it as
984 <quote>bad</quote>.</para>
986 &interaction.bisect.search.bad-init;
988 <para id="x_141">Our next task is to nominate a changeset that we know
989 <emphasis>doesn't</emphasis> have the bug; the <command
990 role="hg-cmd">hg bisect</command> command will
991 <quote>bracket</quote> its search between the first pair of
992 good and bad changesets. In our case, we know that revision
993 10 didn't have the bug. (I'll have more words about choosing
994 the first <quote>good</quote> changeset later.)</para>
996 &interaction.bisect.search.good-init;
998 <para id="x_142">Notice that this command printed some output.</para>
999 <itemizedlist>
1000 <listitem><para id="x_143">It told us how many changesets it must
1001 consider before it can identify the one that introduced
1002 the bug, and how many tests that will require.</para>
1003 </listitem>
1004 <listitem><para id="x_144">It updated the working directory to the next
1005 changeset to test, and told us which changeset it's
1006 testing.</para>
1007 </listitem></itemizedlist>
1009 <para id="x_145">We now run our test in the working directory. We use the
1010 <command>grep</command> command to see if our
1011 <quote>bad</quote> file is present in the working directory.
1012 If it is, this revision is bad; if not, this revision is good.
1013 &interaction.bisect.search.step1;</para>
1015 <para id="x_146">This test looks like a perfect candidate for automation,
1016 so let's turn it into a shell function.</para>
1017 &interaction.bisect.search.mytest;
1019 <para id="x_147">We can now run an entire test step with a single command,
1020 <literal>mytest</literal>.</para>
1022 &interaction.bisect.search.step2;
1024 <para id="x_148">A few more invocations of our canned test step command,
1025 and we're done.</para>
1027 &interaction.bisect.search.rest;
1029 <para id="x_149">Even though we had 40 changesets to search through, the
1030 <command role="hg-cmd">hg bisect</command> command let us find
1031 the changeset that introduced our <quote>bug</quote> with only
1032 five tests. Because the number of tests that the <command
1033 role="hg-cmd">hg bisect</command> command performs grows
1034 logarithmically with the number of changesets to search, the
1035 advantage that it has over the <quote>brute force</quote>
1036 search approach increases with every changeset you add.</para>
1038 </sect2>
1039 <sect2>
1040 <title>Cleaning up after your search</title>
1042 <para id="x_14a">When you're finished using the <command role="hg-cmd">hg
1043 bisect</command> command in a repository, you can use the
1044 <command role="hg-cmd">hg bisect --reset</command> command to
1045 drop the information it was using to drive your search. The
1046 command doesn't use much space, so it doesn't matter if you
1047 forget to run this command. However, <command
1048 role="hg-cmd">hg bisect</command> won't let you start a new
1049 search in that repository until you do a <command
1050 role="hg-cmd">hg bisect --reset</command>.</para>
1052 &interaction.bisect.search.reset;
1054 </sect2>
1055 </sect1>
1056 <sect1>
1057 <title>Tips for finding bugs effectively</title>
1059 <sect2>
1060 <title>Give consistent input</title>
1062 <para id="x_14b">The <command role="hg-cmd">hg bisect</command> command
1063 requires that you correctly report the result of every test
1064 you perform. If you tell it that a test failed when it really
1065 succeeded, it <emphasis>might</emphasis> be able to detect the
1066 inconsistency. If it can identify an inconsistency in your
1067 reports, it will tell you that a particular changeset is both
1068 good and bad. However, it can't do this perfectly; it's about
1069 as likely to report the wrong changeset as the source of the
1070 bug.</para>
1072 </sect2>
1073 <sect2>
1074 <title>Automate as much as possible</title>
1076 <para id="x_14c">When I started using the <command role="hg-cmd">hg
1077 bisect</command> command, I tried a few times to run my
1078 tests by hand, on the command line. This is an approach that
1079 I, at least, am not suited to. After a few tries, I found
1080 that I was making enough mistakes that I was having to restart
1081 my searches several times before finally getting correct
1082 results.</para>
1084 <para id="x_14d">My initial problems with driving the <command
1085 role="hg-cmd">hg bisect</command> command by hand occurred
1086 even with simple searches on small repositories; if the
1087 problem you're looking for is more subtle, or the number of
1088 tests that <command role="hg-cmd">hg bisect</command> must
1089 perform increases, the likelihood of operator error ruining
1090 the search is much higher. Once I started automating my
1091 tests, I had much better results.</para>
1093 <para id="x_14e">The key to automated testing is twofold:</para>
1094 <itemizedlist>
1095 <listitem><para id="x_14f">always test for the same symptom, and</para>
1096 </listitem>
1097 <listitem><para id="x_150">always feed consistent input to the <command
1098 role="hg-cmd">hg bisect</command> command.</para>
1099 </listitem></itemizedlist>
1100 <para id="x_151">In my tutorial example above, the <command>grep</command>
1101 command tests for the symptom, and the <literal>if</literal>
1102 statement takes the result of this check and ensures that we
1103 always feed the same input to the <command role="hg-cmd">hg
1104 bisect</command> command. The <literal>mytest</literal>
1105 function marries these together in a reproducible way, so that
1106 every test is uniform and consistent.</para>
1108 </sect2>
1109 <sect2>
1110 <title>Check your results</title>
1112 <para id="x_152">Because the output of a <command role="hg-cmd">hg
1113 bisect</command> search is only as good as the input you
1114 give it, don't take the changeset it reports as the absolute
1115 truth. A simple way to cross-check its report is to manually
1116 run your test at each of the following changesets:</para>
1117 <itemizedlist>
1118 <listitem><para id="x_153">The changeset that it reports as the first bad
1119 revision. Your test should still report this as
1120 bad.</para>
1121 </listitem>
1122 <listitem><para id="x_154">The parent of that changeset (either parent,
1123 if it's a merge). Your test should report this changeset
1124 as good.</para>
1125 </listitem>
1126 <listitem><para id="x_155">A child of that changeset. Your test should
1127 report this changeset as bad.</para>
1128 </listitem></itemizedlist>
1130 </sect2>
1131 <sect2>
1132 <title>Beware interference between bugs</title>
1134 <para id="x_156">It's possible that your search for one bug could be
1135 disrupted by the presence of another. For example, let's say
1136 your software crashes at revision 100, and worked correctly at
1137 revision 50. Unknown to you, someone else introduced a
1138 different crashing bug at revision 60, and fixed it at
1139 revision 80. This could distort your results in one of
1140 several ways.</para>
1142 <para id="x_157">It is possible that this other bug completely
1143 <quote>masks</quote> yours, which is to say that it occurs
1144 before your bug has a chance to manifest itself. If you can't
1145 avoid that other bug (for example, it prevents your project
1146 from building), and so can't tell whether your bug is present
1147 in a particular changeset, the <command role="hg-cmd">hg
1148 bisect</command> command cannot help you directly. Instead,
1149 you can mark a changeset as untested by running <command
1150 role="hg-cmd">hg bisect --skip</command>.</para>
1152 <para id="x_158">A different problem could arise if your test for a bug's
1153 presence is not specific enough. If you check for <quote>my
1154 program crashes</quote>, then both your crashing bug and an
1155 unrelated crashing bug that masks it will look like the same
1156 thing, and mislead <command role="hg-cmd">hg
1157 bisect</command>.</para>
1159 <para id="x_159">Another useful situation in which to use <command
1160 role="hg-cmd">hg bisect --skip</command> is if you can't
1161 test a revision because your project was in a broken and hence
1162 untestable state at that revision, perhaps because someone
1163 checked in a change that prevented the project from
1164 building.</para>
1166 </sect2>
1167 <sect2>
1168 <title>Bracket your search lazily</title>
1170 <para id="x_15a">Choosing the first <quote>good</quote> and
1171 <quote>bad</quote> changesets that will mark the end points of
1172 your search is often easy, but it bears a little discussion
1173 nevertheless. From the perspective of <command
1174 role="hg-cmd">hg bisect</command>, the <quote>newest</quote>
1175 changeset is conventionally <quote>bad</quote>, and the older
1176 changeset is <quote>good</quote>.</para>
1178 <para id="x_15b">If you're having trouble remembering when a suitable
1179 <quote>good</quote> change was, so that you can tell <command
1180 role="hg-cmd">hg bisect</command>, you could do worse than
1181 testing changesets at random. Just remember to eliminate
1182 contenders that can't possibly exhibit the bug (perhaps
1183 because the feature with the bug isn't present yet) and those
1184 where another problem masks the bug (as I discussed
1185 above).</para>
1187 <para id="x_15c">Even if you end up <quote>early</quote> by thousands of
1188 changesets or months of history, you will only add a handful
1189 of tests to the total number that <command role="hg-cmd">hg
1190 bisect</command> must perform, thanks to its logarithmic
1191 behavior.</para>
1193 </sect2>
1194 </sect1>
1195 </chapter>
1197 <!--
1198 local variables:
1199 sgml-parent-document: ("00book.xml" "book" "chapter")
1200 end:
1201 -->