hgbook

view en/undo.tex @ 121:9094c9fda8ec

Start chapter on error recovery.
author Bryan O'Sullivan <bos@serpentine.com>
date Wed Nov 15 15:59:41 2006 -0800 (2006-11-15)
parents
children 3af28630fe8c
line source
1 \chapter{Finding and fixing your mistakes}
2 \label{chap:undo}
4 To err might be human, but to really handle the consequences well
5 takes a top-notch revision control system. In this chapter, we'll
6 discuss some of the techniques you can use when you find that a
7 problem has crept into your project. Mercurial has some highly
8 capable features that will help you to isolate the sources of
9 problems, and to handle them appropriately.
11 \section{Easily recovered errors}
13 \subsection{The accidental commit}
15 I have the occasional but persistent problem of typing rather more
16 quickly than I can think, which sometimes results in me committing a
17 changeset that is either incomplete or plain wrong. In my case, the
18 usual kind of incomplete changeset is one in which I've created a new
19 source file, but forgotten to \hgcmd{add} it. A ``plain wrong''
20 changeset is not as common, but no less annoying.
22 \subsection{Rolling back a transaction}
24 In section~\ref{sec:concepts:txn}, I mentioned that Mercurial treats
25 each modification of a repository as a \emph{transaction}. Every time
26 you commit a changeset or pull changes from another repository,
27 Mercurial remembers what you did. You can undo, or \emph{roll back},
28 exactly one of these actions using the \hgcmd{rollback} command.
30 Here's a mistake that I often find myself making: committing a change
31 in which I've created a new file, but forgotten to \hgcmd{add} it.
32 \interaction{rollback.commit}
33 Looking at the output of \hgcmd{status} after the commit immediately
34 confirms the error.
35 \interaction{rollback.status}
36 The commit captured the changes to the file \filename{a}, but not the
37 new file \filename{b}. If I were to push this changeset to a
38 repository that I shared with a colleague, the chances are high that
39 something in \filename{a} would refer to \filename{b}, which would not
40 be present in their repository when they pulled my changes. I would
41 thus become the object of some indignation.
43 However, luck is with me---I've caught my error before I pushed the
44 changeset. I use the \hgcmd{rollback} command, and Mercurial makes
45 that last changeset vanish.
46 \interaction{rollback.rollback}
47 Notice that the changeset is no longer present in the repository's
48 history, and the working directory once again thinks that the file
49 \filename{a} is modified. The changeset has been completely erased.
50 I can now safely \hgcmd{add} the file \filename{b}, and rerun my
51 commit.
52 \interaction{rollback.add}
54 \subsection{The erroneous pull}
56 It's common practice with Mercurial to maintain separate development
57 branches of a project in different repositories. Your development
58 team might have one shared repository for your project's ``0.9''
59 release, and another, containing different changes, for the ``1.0''
60 release.
62 Given this, you can imagine that the consequences could be messy if
63 you had a local ``0.9'' repository, and accidentally pulled changes
64 from the shared ``1.0'' repository into it. At worst, you could be
65 paying insufficient attention, and push those changes into the shared
66 ``0.9'' tree, confusing your entire team (but don't worry, we'll
67 return to this horror scenario later). However, it's more likely that
68 you'll notice immediately, because Mercurial will display the URL it's
69 pulling from, or you will see it pull a suspiciously large number of
70 changes into the repository.
72 The \hgcmd{rollback} command will work nicely to expunge all of the
73 changesets that you just pulled. Mercurial groups all changes from
74 one \hgcmd{pull} into a single transaction, so one \hgcmd{rollback} is
75 all you need to undo this mistake.
77 \subsection{Rolling back is useless once you've pushed}
79 The value of the \hgcmd{rollback} command drops to zero once you've
80 pushed your changes to another repository. Rolling back a change
81 makes it disappear entirely, but \emph{only} in the repository in
82 which you perform the \hgcmd{rollback}. Because a rollback eliminates
83 history, there's no way for the disappearance of a change to propagate
84 between repositories.
86 If you've pushed a change to another repository---particularly if it's
87 a shared repository---it has essentially ``escaped into the wild,''
88 and you'll have to recover from your mistake in a different way. What
89 will happen if you push a changeset somewhere, then roll it back, then
90 pull from the repository you pushed to, is that the changeset will
91 reappear in your repository.
93 (If you absolutely know for sure that the change you want to roll back
94 is the most recent change in the repository that you pushed to,
95 \emph{and} you know that nobody else could have pulled it from that
96 repository, you can roll back the changeset there, too, but you really
97 should really not rely on this working reliably. If you do this,
98 sooner or later a change really will make it into a repository that
99 you don't directly control (or have forgotten about), and come back to
100 bite you.)
102 \subsection{You can only roll back once}
104 Mercurial stores exactly one transaction in its transaction log; that
105 transaction is the most recent one that occurred in the repository.
106 This means that you can only roll back one transaction. If you expect
107 to be able to roll back one transaction, then its predecessor, this is
108 not the behaviour you will get.
109 \interaction{rollback.twice}
110 Once you've rolled back one transaction in a repository, you can't
111 roll back again in that repository until you perform another commit or
112 pull.
114 %%% Local Variables:
115 %%% mode: latex
116 %%% TeX-master: "00book"
117 %%% End: