comparison en/ch08-undo.xml @ 807:7226e5e750a6

Clean up chapter 8, and add content
author Bryan O'Sullivan <bos@serpentine.com>
date Tue, 21 Apr 2009 23:49:27 -0700
parents b338f5490029
children 557552d4699f
comparison
equal deleted inserted replaced
806:06458701453c 807:7226e5e750a6
125 125
126 <para id="x_de">If you've pushed a change to another 126 <para id="x_de">If you've pushed a change to another
127 repository&emdash;particularly if it's a shared 127 repository&emdash;particularly if it's a shared
128 repository&emdash;it has essentially <quote>escaped into the 128 repository&emdash;it has essentially <quote>escaped into the
129 wild,</quote> and you'll have to recover from your mistake 129 wild,</quote> and you'll have to recover from your mistake
130 in a different way. What will happen if you push a changeset 130 in a different way. If you push a changeset somewhere, then
131 somewhere, then roll it back, then pull from the repository 131 roll it back, then pull from the repository you pushed to, the
132 you pushed to, is that the changeset will reappear in your 132 changeset you thought you'd gotten rid of will simply reappear
133 repository.</para> 133 in your repository.</para>
134 134
135 <para id="x_df">(If you absolutely know for sure that the change you want 135 <para id="x_df">(If you absolutely know for sure that the change
136 to roll back is the most recent change in the repository that 136 you want to roll back is the most recent change in the
137 you pushed to, <emphasis>and</emphasis> you know that nobody 137 repository that you pushed to, <emphasis>and</emphasis> you
138 else could have pulled it from that repository, you can roll 138 know that nobody else could have pulled it from that
139 back the changeset there, too, but you really should really 139 repository, you can roll back the changeset there, too, but
140 not rely on this working reliably. If you do this, sooner or 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 141 later a change really will make it into a repository that you
142 don't directly control (or have forgotten about), and come 142 don't directly control (or have forgotten about), and come
143 back to bite you.)</para> 143 back to bite you.)</para>
144 144
145 </sect2> 145 </sect2>
190 provides us with an extra degree of safety by saving our 190 provides us with an extra degree of safety by saving our
191 modified file with a <filename>.orig</filename> 191 modified file with a <filename>.orig</filename>
192 extension.</para> 192 extension.</para>
193 193
194 &interaction.daily.revert.status; 194 &interaction.daily.revert.status;
195
196 <tip>
197 <title>Be careful with <filename>.orig</filename> files</title>
198
199 <para>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>
195 210
196 <para id="x_e6">Here is a summary of the cases that the <command 211 <para id="x_e6">Here is a summary of the cases that the <command
197 role="hg-cmd">hg revert</command> command can deal with. We 212 role="hg-cmd">hg revert</command> command can deal with. We
198 will describe each of these in more detail in the section that 213 will describe each of these in more detail in the section that
199 follows.</para> 214 follows.</para>
247 afterwards, untracked. Since a copy doesn't affect the 262 afterwards, untracked. Since a copy doesn't affect the
248 copied-from file in any way, Mercurial doesn't do anything 263 copied-from file in any way, Mercurial doesn't do anything
249 with the copied-from file.</para> 264 with the copied-from file.</para>
250 265
251 &interaction.daily.revert.copy; 266 &interaction.daily.revert.copy;
252
253 <sect3>
254 <title>A slightly special case: reverting a rename</title>
255
256 <para id="x_ef">If you <command role="hg-cmd">hg rename</command> a
257 file, there is one small detail that you should remember.
258 When you <command role="hg-cmd">hg revert</command> a
259 rename, it's not enough to provide the name of the
260 renamed-to file, as you can see here.</para>
261
262 &interaction.daily.revert.rename;
263
264 <para id="x_f0">As you can see from the output of <command
265 role="hg-cmd">hg status</command>, the renamed-to file is
266 no longer identified as added, but the
267 renamed-<emphasis>from</emphasis> file is still removed!
268 This is counter-intuitive (at least to me), but at least
269 it's easy to deal with.</para>
270
271 &interaction.daily.revert.rename-orig;
272
273 <para id="x_f1">So remember, to revert a <command role="hg-cmd">hg
274 rename</command>, you must provide
275 <emphasis>both</emphasis> the source and destination
276 names.</para>
277
278 <para id="x_f2">% TODO: the output doesn't look like it will be
279 removed!</para>
280
281 <para id="x_f3">(By the way, if you rename a file, then modify the
282 renamed-to file, then revert both components of the rename,
283 when Mercurial restores the file that was removed as part of
284 the rename, it will be unmodified. If you need the
285 modifications in the renamed-to file to show up in the
286 renamed-from file, don't forget to copy them over.)</para>
287
288 <para id="x_f4">These fiddly aspects of reverting a rename arguably
289 constitute a small bug in Mercurial.</para>
290
291 </sect3>
292 </sect2> 267 </sect2>
293 </sect1> 268 </sect1>
269
294 <sect1> 270 <sect1>
295 <title>Dealing with committed changes</title> 271 <title>Dealing with committed changes</title>
296 272
297 <para id="x_f5">Consider a case where you have committed a change $a$, and 273 <para id="x_f5">Consider a case where you have committed a change
298 another change $b$ on top of it; you then realise that change 274 <emphasis>a</emphasis>, and another change
299 $a$ was incorrect. Mercurial lets you <quote>back out</quote> 275 <emphasis>b</emphasis> on top of it; you then realise that
300 an entire changeset automatically, and building blocks that let 276 change <emphasis>a</emphasis> was incorrect. Mercurial lets you
301 you reverse part of a changeset by hand.</para> 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>
302 280
303 <para id="x_f6">Before you read this section, here's something to 281 <para id="x_f6">Before you read this section, here's something to
304 keep in mind: the <command role="hg-cmd">hg backout</command> 282 keep in mind: the <command role="hg-cmd">hg backout</command>
305 command undoes changes by <emphasis>adding</emphasis> history, 283 command undoes the effect of a change by
306 not by modifying or erasing it. It's the right tool to use if 284 <emphasis>adding</emphasis> to your repository's history, not by
307 you're fixing bugs, but not if you're trying to undo some change 285 modifying or erasing it. It's the right tool to use if you're
308 that has catastrophic consequences. To deal with those, see 286 fixing bugs, but not if you're trying to undo some change that
287 has catastrophic consequences. To deal with those, see
309 <xref linkend="sec:undo:aaaiiieee"/>.</para> 288 <xref linkend="sec:undo:aaaiiieee"/>.</para>
310 289
311 <sect2> 290 <sect2>
312 <title>Backing out a changeset</title> 291 <title>Backing out a changeset</title>
313 292
390 369
391 &interaction.backout.non-tip.cat; 370 &interaction.backout.non-tip.cat;
392 371
393 <para id="x_100">As the graphical history in <xref 372 <para id="x_100">As the graphical history in <xref
394 linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial 373 linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial
395 actually commits <emphasis>two</emphasis> changes in this kind 374 still commits one change in this kind of situation (the
396 of situation (the box-shaped nodes are the ones that Mercurial 375 box-shaped node is the ones that Mercurial commits
397 commits automatically). Before Mercurial begins the backout 376 automatically), but the revision graph now looks different.
398 process, it first remembers what the current parent of the 377 Before Mercurial begins the backout process, it first
399 working directory is. It then backs out the target changeset, 378 remembers what the current parent of the working directory is.
400 and commits that as a changeset. Finally, it merges back to 379 It then backs out the target changeset, and commits that as a
401 the previous parent of the working directory, and commits the 380 changeset. Finally, it merges back to the previous parent of
402 result of the merge.</para> 381 the working directory, but notice that it <emphasis>does not
403 382 commit</emphasis> the result of the merge. The repository
404 <para id="x_101">% TODO: to me it looks like mercurial doesn't commit the 383 now contains two heads, and the working directory is in a
405 second merge automatically!</para> 384 merge state.</para>
406 385
407 <figure id="fig:undo:backout-non-tip"> 386 <figure id="fig:undo:backout-non-tip">
408 <title>Automated backout of a non-tip change using the 387 <title>Automated backout of a non-tip change using the
409 <command role="hg-cmd">hg backout</command> command</title> 388 <command role="hg-cmd">hg backout</command> command</title>
410 <mediaobject> 389 <mediaobject>
414 </figure> 393 </figure>
415 394
416 <para id="x_103">The result is that you end up <quote>back where you 395 <para id="x_103">The result is that you end up <quote>back where you
417 were</quote>, only with some extra history that undoes the 396 were</quote>, only with some extra history that undoes the
418 effect of the changeset you wanted to back out.</para> 397 effect of the changeset you wanted to back out.</para>
398
399 <para>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>
419 406
420 <sect3> 407 <sect3>
421 <title>Always use the <option 408 <title>Always use the <option
422 role="hg-opt-backout">--merge</option> option</title> 409 role="hg-opt-backout">--merge</option> option</title>
423 410
528 <quote>clean</quote>, i.e. that the output of <command 515 <quote>clean</quote>, i.e. that the output of <command
529 role="hg-cmd">hg status</command> would be empty.</para> 516 role="hg-cmd">hg status</command> would be empty.</para>
530 </listitem> 517 </listitem>
531 <listitem><para id="x_112">It remembers the current parent of the working 518 <listitem><para id="x_112">It remembers the current parent of the working
532 directory. Let's call this changeset 519 directory. Let's call this changeset
533 <literal>orig</literal></para> 520 <literal>orig</literal>.</para>
534 </listitem> 521 </listitem>
535 <listitem><para id="x_113">It does the equivalent of a <command 522 <listitem><para id="x_113">It does the equivalent of a <command
536 role="hg-cmd">hg update</command> to sync the working 523 role="hg-cmd">hg update</command> to sync the working
537 directory to the changeset you want to back out. Let's 524 directory to the changeset you want to back out. Let's
538 call this changeset <literal>backout</literal></para> 525 call this changeset <literal>backout</literal>.</para>
539 </listitem> 526 </listitem>
540 <listitem><para id="x_114">It finds the parent of that changeset. Let's 527 <listitem><para id="x_114">It finds the parent of that changeset. Let's
541 call that changeset <literal>parent</literal>.</para> 528 call that changeset <literal>parent</literal>.</para>
542 </listitem> 529 </listitem>
543 <listitem><para id="x_115">For each file that the 530 <listitem><para id="x_115">For each file that the
630 will reappear in your local repository the next time you 617 will reappear in your local repository the next time you
631 pull.</para> 618 pull.</para>
632 619
633 <para id="x_120">If a situation like this arises, and you know which 620 <para id="x_120">If a situation like this arises, and you know which
634 repositories your bad change has propagated into, you can 621 repositories your bad change has propagated into, you can
635 <emphasis>try</emphasis> to get rid of the changeefrom 622 <emphasis>try</emphasis> to get rid of the change from
636 <emphasis>every</emphasis> one of those repositories. This is, 623 <emphasis>every</emphasis> one of those repositories. This is,
637 of course, not a satisfactory solution: if you miss even a 624 of course, not a satisfactory solution: if you miss even a
638 single repository while you're expunging, the change is still 625 single repository while you're expunging, the change is still
639 <quote>in the wild</quote>, and could propagate further.</para> 626 <quote>in the wild</quote>, and could propagate further.</para>
640 627
642 <emphasis>after</emphasis> the change that you'd like to see 629 <emphasis>after</emphasis> the change that you'd like to see
643 disappear, your options are further reduced. Mercurial doesn't 630 disappear, your options are further reduced. Mercurial doesn't
644 provide a way to <quote>punch a hole</quote> in history, leaving 631 provide a way to <quote>punch a hole</quote> in history, leaving
645 changesets intact.</para> 632 changesets intact.</para>
646 633
647 <para id="x_122">XXX This needs filling out. The 634 <sect2>
648 <literal>hg-replay</literal> script in the 635 <title>Backing out a merge</title>
649 <literal>examples</literal> directory works, but doesn't handle 636
650 merge changesets. Kind of an important omission.</para> 637 <para>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>
643
644 <para>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>
653
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>
661
662 <para>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>
666
667 <para>One way to do so would be as follows.</para>
668
669 <orderedlist>
670 <listitem>
671 <para>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>
686
687 <listitem>
688 <para>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>
704
705 <listitem>
706 <para>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>
718
719 <listitem>
720 <para>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>
651 733
652 <sect2> 734 <sect2>
653 <title>Protect yourself from <quote>escaped</quote> 735 <title>Protect yourself from <quote>escaped</quote>
654 changes</title> 736 changes</title>
655 737
668 configuration in place, some kinds of bad changeset will 750 configuration in place, some kinds of bad changeset will
669 naturally tend to <quote>die out</quote> because they can't 751 naturally tend to <quote>die out</quote> because they can't
670 propagate into the central repository. Better yet, this 752 propagate into the central repository. Better yet, this
671 happens without any need for explicit intervention.</para> 753 happens without any need for explicit intervention.</para>
672 754
673 <para id="x_125">For instance, an incoming change hook that verifies that a 755 <para id="x_125">For instance, an incoming change hook that
674 changeset will actually compile can prevent people from 756 verifies that a changeset will actually compile can prevent
675 inadvertantly <quote>breaking the build</quote>.</para> 757 people from inadvertently <quote>breaking the
676 758 build</quote>.</para>
759 </sect2>
760
761 <sect2>
762 <title>What to do about sensitive changes that escape</title>
763
764 <para>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>
767
768 <para>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>
778
779 <para>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>
783
784 <para>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>
795
796 <para>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>
677 </sect2> 808 </sect2>
678 </sect1> 809 </sect1>
810
679 <sect1 id="sec:undo:bisect"> 811 <sect1 id="sec:undo:bisect">
680 <title>Finding the source of a bug</title> 812 <title>Finding the source of a bug</title>
681 813
682 <para id="x_126">While it's all very well to be able to back out a changeset 814 <para id="x_126">While it's all very well to be able to back out a changeset
683 that introduced a bug, this requires that you know which 815 that introduced a bug, this requires that you know which
813 <orderedlist> 945 <orderedlist>
814 <listitem><para id="x_138">You run your binary test.</para> 946 <listitem><para id="x_138">You run your binary test.</para>
815 <itemizedlist> 947 <itemizedlist>
816 <listitem><para id="x_139">If the test succeeded, you tell <command 948 <listitem><para id="x_139">If the test succeeded, you tell <command
817 role="hg-cmd">hg bisect</command> by running the 949 role="hg-cmd">hg bisect</command> by running the
818 <command role="hg-cmd">hg bisect good</command> 950 <command role="hg-cmd">hg bisect --good</command>
819 command.</para> 951 command.</para>
820 </listitem> 952 </listitem>
821 <listitem><para id="x_13a">If it failed, run the <command 953 <listitem><para id="x_13a">If it failed, run the <command
822 role="hg-cmd">hg bisect bad</command> 954 role="hg-cmd">hg bisect --bad</command>
823 command.</para></listitem></itemizedlist> 955 command.</para></listitem></itemizedlist>
824 </listitem> 956 </listitem>
825 <listitem><para id="x_13b">The command uses your information to decide 957 <listitem><para id="x_13b">The command uses your information to decide
826 which changeset to test next.</para> 958 which changeset to test next.</para>
827 </listitem> 959 </listitem>
907 <sect2> 1039 <sect2>
908 <title>Cleaning up after your search</title> 1040 <title>Cleaning up after your search</title>
909 1041
910 <para id="x_14a">When you're finished using the <command role="hg-cmd">hg 1042 <para id="x_14a">When you're finished using the <command role="hg-cmd">hg
911 bisect</command> command in a repository, you can use the 1043 bisect</command> command in a repository, you can use the
912 <command role="hg-cmd">hg bisect reset</command> command to 1044 <command role="hg-cmd">hg bisect --reset</command> command to
913 drop the information it was using to drive your search. The 1045 drop the information it was using to drive your search. The
914 command doesn't use much space, so it doesn't matter if you 1046 command doesn't use much space, so it doesn't matter if you
915 forget to run this command. However, <command 1047 forget to run this command. However, <command
916 role="hg-cmd">hg bisect</command> won't let you start a new 1048 role="hg-cmd">hg bisect</command> won't let you start a new
917 search in that repository until you do a <command 1049 search in that repository until you do a <command
918 role="hg-cmd">hg bisect reset</command>.</para> 1050 role="hg-cmd">hg bisect --reset</command>.</para>
919 1051
920 &interaction.bisect.search.reset; 1052 &interaction.bisect.search.reset;
921 1053
922 </sect2> 1054 </sect2>
923 </sect1> 1055 </sect1>