Mercurial > hgbook
changeset 837:b775f963b18c
Clean up chapter 8, and add content
propagate 7226e5e750a6
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 15 Sep 2009 22:32:03 +0900 |
parents | d819bc2414f4 |
children | d1f676a6a4b3 |
files | ja/Makefile.tex ja/undo.tex |
diffstat | 2 files changed, 313 insertions(+), 118 deletions(-) [+] |
line wrap: on
line diff
--- a/ja/Makefile.tex Thu Jul 23 18:10:58 2009 +0900 +++ b/ja/Makefile.tex Tue Sep 15 22:32:03 2009 +0900 @@ -43,6 +43,11 @@ undo-manual-merge.dot \ undo-non-tip.dot \ undo-simple.dot \ + figs/bad-merge-1.dot \ + figs/bad-merge-2.dot \ + figs/bad-merge-3.dot \ + figs/bad-merge-4.dot \ + figs/bad-merge-5.dot \ wdir.svg \ wdir-after-commit.svg \ wdir-branch.svg \
--- a/ja/undo.tex Thu Jul 23 18:10:58 2009 +0900 +++ b/ja/undo.tex Tue Sep 15 22:32:03 2009 +0900 @@ -164,31 +164,30 @@ %If you've pushed a change to another repository---particularly if it's a %shared repository---it has essentially ``escaped into the wild,'' and -%you'll have to recover from your mistake in a different way. What will -%happen if you push a changeset somewhere, then roll it back, then pull -%from the repository you pushed to, is that the changeset will reappear -%in your repository. +%you'll have to recover from your mistake in a different way. +%If you push a changeset somewhere, then roll it back, then pull from the +%repository you pushed to, the changeset you thought you'd gotten rid of +%will simply reappear in your repository. $B$b$7$"$J$?$,B>$N%j%]%8%H%j!JFC$K6&M-%j%]%8%H%j!K$KJQ99$r%W%C%7%e$7$F$$$k(B $B$N$J$i!$:$$C$?;vBV$,5/$3$C$F$*$j!$JL$NJ}K!$G%_%9$+$iI|5l$9$kI,MW$,$"$k!%(B $B%A%'%s%8%;%C%H$r$I$3$+$X%W%C%7%e$7$?8e$G%m!<%k%P%C%/$7!$%W%C%7%e@h$N%j%](B -$B%8%H%j$+$i:F$S%W%k$7$?>l9g!$%A%'%s%8%;%C%H$,%m!<%+%k%j%]%8%H%j$K:F$S8=$l(B -$B$k!%(B +$B%8%H%j$+$i:F$S%W%k$7$?>l9g!$:o=|$7$?$D$b$j$N%A%'%s%8%;%C%H$,%m!<%+%k%j%](B +$B%8%H%j$K:F$S8=$l$k!%(B %(If you absolutely know for sure that the change you want to roll back %is the most recent change in the repository that you pushed to, %\emph{and} you know that nobody else could have pulled it from that %repository, you can roll back the changeset there, too, but you really -%should really not rely on this working reliably. If you do this, -%sooner or later a change really will make it into a repository that -%you don't directly control (or have forgotten about), and come back to -%bite you.) +%should not expect this to work reliably. Sooner or later a change +%really will make it into a repository that you don't directly control +%(or have forgotten about), and come back to bite you.) $B!J$b$7%m!<%k%P%C%/$7$?$$%A%'%s%8%;%C%H$,%W%C%7%e@h$N%j%]%8%H%j$G:G?7$G$"(B -$B$j!$$+$D!$C/$b$=$l$r%W%k$7$F$$$J$$$3$H$,3N<B$G$"$k>l9g$O!$%W%C%7%e@h$N%j(B -$B%]%8%H%j$G%m!<%k%P%C%/$9$k$3$H$,2DG=$@$,!$$3$NJ}K!$O3N<B$G$O$J$$$H$$$&$3(B -$B$H$r4N$KL?$8$F$*$/$Y$-$G$"$k!%$3$NJ}K!$OD>@\%3%s%H%m!<%k$G$-$J$+$C$?$j!$(B -$B$=$NJ}K!$rK:$l$F$7$^$C$?%j%]%8%H%j$X$NJQ99$N=$@5$K$O;H$($J$$!%!K(B +$B$j!$$+$D!$C/$b$=$l$r%W%k$7$F$$$J$$$3$H$,3N<B$J>l9g$O!$%W%C%7%e@h$N%j%]%8(B +$B%H%j$G%m!<%k%P%C%/$9$k$3$H$,2DG=$G$"$k!%$7$+$7$3$NJ}K!$K$O3N<B@-$,$J$$$H(B +$B$$$&$3$H$r4N$KL?$8$F$*$/$Y$-$G$"$k!%$3$NJ}K!$OD>@\%3%s%H%m!<%k$G$-$J$+$C(B +$B$?$j!$$=$NJ}K!$rK:$l$F$7$^$C$?%j%]%8%H%j$X$NJQ99$N=$@5$K$O;H$($J$$!%!K(B %\subsection{You can only roll back once} @@ -248,6 +247,26 @@ $B$r%;!<%V$9$k!%(B \interaction{daily.revert.status} +\begin{note} +%Be careful with \filename{.orig} files +\filename{.orig}$B%U%!%$%k$KCm0U(B + +%It's extremely unlikely that you are either using Mercurial to manage +%files with \filename{.orig} extensions or that you even care about the +%contents of such files. Just in case, though, it's useful to remember +%that \hgcmd{revert} will unconditionally overwrite an existing file with +%a \filename{.orig} extension. For instance, if you already have a file +%named \filename{foo.orig} when you revert \filename{foo}, the contents +%of \filename{foo.orig} will be clobbered. + +\filename{.orig}$B$H$$$&3HD%;R$r;}$D%U%!%$%k$r(BMercurial$B$G4IM}$7$?$j!$$=$NFb(B +$BMF$K4X?4$r;}$D$3$H$O$*$=$i$/$[$H$s$I$J$$$@$m$&!%$=$&$G$J$$>l9g$O(B +\hgcmd{revert}$B$,L5>r7o$K3HD%;R(B\filename{.orig}$B$N%U%!%$%k$r>e=q$-$9$k$3$H(B +$B$KN10U$9$Y$-$G$"$k!%Nc$r5s$2$k$H(B\filename{foo.orig}$B$H$$$&%U%!%$%k$,$"$k$H(B +$B$-!$(B\filename{foo}$B$r(Brevert$B$9$k$H(B\filename{foo.orig}$B$NCf?H$OB;$J$o$l$F$7$^(B +$B$&!%(B +\end{note} + %Here is a summary of the cases that the \hgcmd{revert} command can %deal with. We will describe each of these in more detail in the %section that follows. @@ -331,75 +350,31 @@ $B$H$b$J$$!%(B -%\subsubsection{A slightly special case: reverting a rename} -\subsubsection{$B$d$dFC<l$J%1!<%9!'%j%M!<%`$N<h$j>C$7(B} - -%If you \hgcmd{rename} a file, there is one small detail that -%you should remember. When you \hgcmd{revert} a rename, it's not -%enough to provide the name of the renamed-to file, as you can see -%here. -%As you can see from the output of \hgcmd{status}, the renamed-to file -%is no longer identified as added, but the renamed-\emph{from} file is -%still removed! This is counter-intuitive (at least to me), but at -%least it's easy to deal with. -%So remember, to revert a \hgcmd{rename}, you must provide \emph{both} -%the source and destination names. - -\hgcmd{rename}$B$7$?8e$G$O!$>/$7N10U$7$F$*$/$Y$-E@$,$"$k!%%j%M!<%`8e$K(B -\hgcmd{revert}$B$7$?>l9g!$$3$3$G@bL@$9$k$h$&$K!$%j%M!<%`$7$?%U%!%$%k$NL>A0(B -$B$r;XDj$9$k$@$1$G$OIT==J,$G$"$k!%(B -\interaction{daily.revert.rename} -\hgcmd{status}$B$N=PNO$+$iJ,$+$k$h$&$K!$%j%M!<%`@h$N%U%!%$%k$O$b$O$d(Badd$B$5(B -$B$l$?07$$$K$J$C$F$$$J$$!%$7$+$7%j%M!<%`(B\emph{$B85(B}$B$N%U%!%$%k$O$^$@>C5n$5$l(B -$B$?$^$^$K$J$C$F$$$k!%$3$l$O!J>/$J$/$H$bI.<T$K$H$C$F!KHsD>46E*$@$,!$<h$j07(B -$B$$$O4JC1$G$"$k!%(B -\interaction{daily.revert.rename-orig} -\hgcmd{rename}$B$r<h$j>C$9:]$K$O!$85$N%U%!%$%k$H%j%M!<%`8e$N%U%!%$%k(B -\emph{$BN>J}(B}$B$r;XDj$9$kI,MW$,$"$k!%(B - -%(By the way, if you rename a file, then modify the renamed-to file, -%then revert both components of the rename, when Mercurial restores the -%file that was removed as part of the rename, it will be unmodified. -%If you need the modifications in the renamed-to file to show up in the -%renamed-from file, don't forget to copy them over.) - -$B!J0lJ}!$%j%M!<%`$7$?8e$K%j%M!<%`@h$N%U%!%$%k$rJT=8$7!$%j%M!<%`$NA08e$N%U%!(B -$B%$%kL>$r;XDj$7$F<h$j>C$7$r9T$$!$(BMercurial$B$,%j%M!<%`$N:]$K>C5n$5$l$?%U%!(B -$B%$%k$r=$I|$9$k$H!$$3$N%U%!%$%k$OJT=8A0$N>uBV$K$J$C$F$$$k!%%j%M!<%`8e$N%U%!(B -$B%$%k$X$NJQ99$,%j%M!<%`A0$N%U%!%$%k$K;D$k$h$&$K$9$k$K$O!$%3%T!<$r:n$C$F$*(B -$B$/I,MW$,$"$k!%!K(B - -%These fiddly aspects of reverting a rename arguably constitute a small -%bug in Mercurial. - -$B%j%M!<%`$rI|85$9$k;~$K5/$3$kLq2p$4$H$O$*$=$i$/(BMercurial$B$N%P%0$H8@$($k$+(B -$B$b$7$l$J$$!%(B - - %\section{Dealing with committed changes} \section{$B%3%_%C%H$5$l$?JQ99$N07$$(B} -%Consider a case where you have committed a change $a$, and another -%change $b$ on top of it; you then realise that change $a$ was +%Consider a case where you have committed a change \emph{a}, and another +%change \emph{b} on top of it; you then realise that change \emph{a} was %incorrect. Mercurial lets you ``back out'' an entire changeset %automatically, and building blocks that let you reverse part of a %changeset by hand. -$a$$B$r%3%_%C%H$7$?8e$GJL$N(B$b$$B$r%3%_%C%H$7!$$3$3$G(B$a$$B$O8m$j$G$"$k$3$H$K5$$,(B -$B$D$$$?>l9g$r9M$($k!%(BMercurial$B$O%A%'%s%8%;%C%HA4BN$H%A%'%s%8%;%C%H$N0lItJ,(B -$B$r<j$G%P%C%/%"%&%H$9$k$h$&$KB%$9!%(B +\emph{a}$B$r%3%_%C%H$7$?8e$GJL$N(B\emph{b}$B$r%3%_%C%H$7!$$3$3$G(B\emph{a}$B$,8m$j(B +$B$G$"$k$3$H$K5$$E$$$?>l9g$r9M$($k!%(BMercurial$B$O%A%'%s%8%;%C%HA4BN$H%A%'%s%8(B +$B%;%C%H$N0lItJ,$r<j$G%P%C%/%"%&%H$9$k$h$&$KB%$9!%(B %Before you read this section, here's something to keep in mind: the -%\hgcmd{backout} command undoes changes by \emph{adding} history, not -%by modifying or erasing it. It's the right tool to use if you're -%fixing bugs, but not if you're trying to undo some change that has -%catastrophic consequences. To deal with those, see -%section~\ref{sec:undo:aaaiiieee}. +%\hgcmd{backout} command undoes the effect of a change by \emph{adding} +%to your repository's history, not by modifying or erasing it. It's the +%right tool to use if you're fixing bugs, but not if you're trying to +%undo some change that has catastrophic consequences. To deal with +%those, see section~\ref{sec:undo:aaaiiieee}. -$B$3$N@a$rFI$`A0$K!$(B\hgcmd{backout}$B%3%^%s%I$OMzNr$K(B\emph{$BDI2C(B}$B$9$k$3$H$G<h(B -$B$j>C$7A`:n$r9T$&$3$H$r3P$($F$*$$$FM_$7$$!%JQ99$d>C5n$G$O$J$$!%%P%0$N=$(B -$B@5$N$?$a$KLrN)$D%D!<%k$@$,!$JQ99$N<h$j>C$7$N$?$a$KMQ$$$k$HGKLGE*$J7k2L$r(B -$B$b$?$i$9!%8e<T$NL\E*$N$?$a$K$O(B\ref{sec:undo:aaaiiieee}$B$r;2>H$N$3$H!%(B +$B$3$N@a$rFI$`A0$K!$(B\hgcmd{backout}$B%3%^%s%I$O%j%]%8%H%jMzNr$r?7$?$K(B\emph{$BDI(B +$B2C(B}$B$9$k$3$H$GJQ99$K$h$k1F6A$r<h$j>C$9$3$H$r3P$($F$*$$$FM_$7$$!%MzNr$NJQ99(B +$B$d>C5n$G$O$J$$!%(B\hgcmd{backout}$B$O%P%0$N=$@5$N$?$a$KLrN)$D%D!<%k$@$,!$Bg5,(B +$BLO$J1F6A$r;}$DJQ99$r<h$j>C$9$?$a$N%D!<%k$G$O$J$$!%8e<T$NL\E*$N$?$a$K$O(B +\ref{sec:undo:aaaiiieee}$B$r;2>H$5$l$?$$!%(B %\subsection{Backing out a changeset} \subsection{$B%A%'%s%8%;%C%H$N%P%C%/%"%&%H(B} @@ -496,20 +471,25 @@ \interaction{backout.non-tip.cat} %As the graphical history in figure~\ref{fig:undo:backout-non-tip} -%illustrates, Mercurial actually commits \emph{two} changes in this -%kind of situation (the box-shaped nodes are the ones that Mercurial -%commits automatically). Before Mercurial begins the backout process, -%it first remembers what the current parent of the working directory -%is. It then backs out the target changeset, and commits that as a -%changeset. Finally, it merges back to the previous parent of the -%working directory, and commits the result of the merge. +%illustrates, Mercurial still commits one change in this kind of +%situation (the box-shaped node is the ones that Mercurial commits +%automatically), but the revision graph now looks different. Before +%Mercurial begins the backout process, it first remembers what the +%current parent of the working directory is. It then backs out the +%target changeset, and commits that as a changeset. Finally, it merges +%back to the previous parent of the working directory, but notice that it +%\emph{does not commit} the result of the merge. The repository now +%contains two heads, and the working directory is in a merge state. -$B?^(B\ref{fig:undo:backout-non-tip}$B$G<($5$l$?MzNr$G!$(BMercurial$B$O(B2$B$D$N%3%_%C(B -$B%H$r9T$C$F$$$k!%!J?^Cf$GH"$G<($5$l$?@aE@$O(BMercurial$B$,<+F0E*$K%3%_%C%H$7(B -$B$?JQ99$G$"$k!%!K%P%C%/%"%&%H%W%m%;%9$NA0$K(BMercurial$B$O!$8=:_$N%o!<%-%s%0%G%#(B -$B%l%/%H%j$N?F$,2?$G$"$k$+$r5-21$9$k!%$=$7$F%?!<%2%C%H$N%A%'%s%8%;%C%H$r<h(B -$B$j=|$-!$$3$l$r%A%'%s%8%;%C%H$H$7$F%3%_%C%H$9$k!%:G8e$K%o!<%-%s%0%G%#%l%/(B -$B%H%j$NA0$N?F$X%^!<%8$r9T$$!$%^!<%8$N7k2L$r%3%_%C%H$9$k!%(B +$B?^(B\ref{fig:undo:backout-non-tip}$B$NMzNr%0%i%U$G!$(BMercurial$B$O(B1$B$D$NJQ99$r%3(B +$B%_%C%H$7$F$$$k!J?^Cf$GH"$G<($5$l$?@aE@$O(BMercurial$B$,<+F0E*$K9T$C$?%3%_%C%H(B +$B$G$"$k!%!K$,!$%j%S%8%g%s%0%i%U$K$OJQ2=$,5/$-$F$$$k!%%P%C%/%"%&%H%W%m%;%9(B +$B$NA0$K(BMercurial$B$O!$8=:_$N%o!<%-%s%0%G%#%l%/%H%j$N?F$,2?$G$"$k$+$r5-21$9(B +$B$k!%$=$7$F%?!<%2%C%H$N%A%'%s%8%;%C%H$r<h$j=|$-!$$3$l$r%A%'%s%8%;%C%H$H$7(B +$B$F%3%_%C%H$9$k!%:G8e$K(BMercurial$B$O%o!<%-%s%0%G%#%l%/%H%j$N0JA0$NN>?F$K%^!<(B +$B%8$r9T$&$,!$%^!<%8$N7k2L$r(B\emph{$B%3%_%C%H$7$J$$(B}$B$3$H$KN10U$5$l$?$$!%$3$N;~(B +$BE@$G%j%]%8%H%j$O(B2$B$D$N%X%C%I$r;}$A!$%o!<%-%s%0%G%#%l%/%H%j$O%^!<%8:Q$_$N>u(B +$BBV$K$J$k!%(B \begin{figure}[htb] \centering @@ -524,9 +504,21 @@ %extra history that undoes the effect of the changeset you wanted to %back out. -$B:G=*E*$K!$$$$/$i$+$NM>7W$JMzNr$r;D$7$D$D!$<h$j=|$-$?$+$C$?%A%'%s%8%;%C%H(B -$B$N1F6A$r=|5n$7$F!$K>$`>uBV$KLa$9$3$H$,$G$-$F$$$k!%(B +$B:G=*E*$K!$<h$j=|$-$?$+$C$?%A%'%s%8%;%C%H$N1F6A$r=|5n$7!$MzNr$K=|5n$N5-O?(B +$B$3$=A}$($F$$$k$b$N$N!$K>$`>uBV$KLa$9$3$H$,$G$-$F$$$k!%(B +%You might wonder why Mercurial does not commit the result of the merge +%that it performed. The reason lies in Mercurial behaving +%conservatively: a merge naturally has more scope for error than simply +%undoing the effect of the tip changeset, so your work will be safest if +%you first inspect (and test!) the result of the merge, \emph{then} +%commit it. + +$B$J$<(BMercurial$B$,%^!<%8$N:]$K%3%_%C%H$b9T$o$J$$$N$+5?Ld$K46$8$k$+$b$7$l$J(B +$B$$!%(BMercurial$B$,$3$N$h$&$JF0:n$r$9$kM}M3$O!$%^!<%8$OC1$K(Btip$B%A%'%s%8%;%C%H(B +$B$N8z2L$r<h$j=|$/>l9g$h$j$b%(%i!<$N860x$K$J$kMWAG$,B?$/!$$=$N$?$a!$$^$:%^!<(B +$B%8$N7k2L$r8!::$7!$>l9g$K$h$C$F$O%F%9%H$b9T$C$F!$$=$N>e$G%3%_%C%H$9$Y$-$G(B +$B$"$k$H$$$&9M$($G@_7W$5$l$F$$$k$?$a$G$"$k!%(B %\subsubsection{Always use the \hgopt{backout}{--merge} option} \subsubsection{$B>o$K(B\hgopt{backout}{--merge}$B%*%W%7%g%s$r;H$&(B} @@ -659,10 +651,10 @@ %\item It ensures that the working directory is ``clean'', i.e.~that % the output of \hgcmd{status} would be empty. %\item It remembers the current parent of the working directory. Let's -% call this changeset \texttt{orig} +% call this changeset \texttt{orig}. %\item It does the equivalent of a \hgcmd{update} to sync the working % directory to the changeset you want to back out. Let's call this -% changeset \texttt{backout} +% changeset \texttt{backout}. %\item It finds the parent of that changeset. Let's call that % changeset \texttt{parent}. %\item For each file that the \texttt{backout} changeset affected, it @@ -678,7 +670,7 @@ \hgcmd{backout}$B$,$I$N$h$&$KF0:n$9$k$+407k$K@bL@$9$k$H0J2<$N$h$&$K$J$k!%(B \begin{enumerate} \item $B%o!<%-%s%0%G%#%l%/%H%j$,%/%j!<%s$G$"$k$3$H$r3NG'$9$k!%(Bi.e.\hgcmd{status} - $B$,6u$G$"$k$3$H$r3NG'$9$k(B + $B$,6u$G$"$k$3$H$r3NG'$9$k!%(B \item $B8=:_$N%o!<%-%s%0%G%#%l%/%H%j$N?F$r5-21$9$k!%$3$N%A%'%s%8%;%C%H$r(B \texttt{orig}$B$H8F$V$3$H$K$9$k!%(B \item $B%o!<%-%s%0%G%#%l%/%H%j$r!$%P%C%/%"%&%H$7$?%A%'%s%8%;%C%H$NFbMF$K(B @@ -801,7 +793,7 @@ %If a situation like this arises, and you know which repositories your %bad change has propagated into, you can \emph{try} to get rid of the -%changee from \emph{every} one of those repositories. This is, of +%change from \emph{every} one of those repositories. This is, of %course, not a satisfactory solution: if you miss even a single %repository while you're expunging, the change is still ``in the %wild'', and could propagate further. @@ -820,13 +812,129 @@ $B$?$H$9$l$P!$;H$($k%*%W%7%g%s$O$5$i$K>/$J$/$J$k!%(BMercurial$B$O%A%'%s%8%;%C(B $B%H$r$=$N$^$^$KMzNr$K7j$r3+$1$k$h$&$JJ}K!$rDs6!$7$F$$$J$$!%(B -%XXX This needs filling out. The \texttt{hg-replay} script in the -%\texttt{examples} directory works, but doesn't handle merge -%changesets. Kind of an important omission. + +%\subsection{Backing out a merge} +\subsection{$B%^!<%87k2L$N%P%C%/%"%&%H(B} + +%Since merges are often complicated, it is not unheard of for a merge to +%be mangled badly, but committed erroneously. Mercurial provides an +%important safeguard against bad merges by refusing to commit unresolved +%files, but human ingenuity guarantees that it is still possible to mess +%a merge up and commit it. + +$B%^!<%8$OJ#;($J$3$H$bB?$/!$$R$I$/:xAn$7$?$j!$8m$C$F%3%_%C%H$5$l$k>l9g$b$"(B +$B$k!%(B Mercurial$B$K$O!$L$%j%>%k%V$N%U%!%$%k$N%3%_%C%H$r5qH]$9$k$3$H$G8m$C$?(B +$B%^!<%8$+$i%j%]%8%H%j$r<i$k<jN)$F$,$"$k!%$7$+$7$=$l$G$b%^!<%8>uBV$r:.Mp$5(B +$B$;!$$=$l$r%3%_%C%H$9$k$3$H$,2DG=$G$"$k!%(B + +%Given a bad merge that has been committed, usually the best way to +%approach it is to simply try to repair the damage by hand. A complete +%disaster that cannot be easily fixed up by hand ought to be very rare, +%but the \hgcmd{backout} command may help in making the cleanup +%easier. It offers a \hgopt{backout}{--parent} option, which lets you +%specify which parent to revert to when backing out a merge. + +$B4V0c$C$?%^!<%8$,%3%_%C%H$5$l$?>l9g!$DL>o$O<jF0$G=$I|$r9T$&$N$,:G$bNI$$%"(B +$B%W%m!<%A$G$"$k!%<jF0$G=$I|$G$-$J$$$h$&$JBg;4;v$OLGB?$K$J$$(B +$B$,!$(B\hgcmd{backout}$B%3%^%s%I$,=$I|$N=u$1$K$J$k$+$b$7$l$J(B +$B$$!%(B\hgopt{backout}{--parent}$B%*%W%7%g%s$r;H$&$H!$$I$N?F$+$i%^!<%8$N%P%C%/(B +$B%"%&%H$r9T$&$+$r;XDj$G$-$k!%(B + +\begin{figure}[htb] + \centering + \grafix{figs/bad-merge-1} + %<imageobject><imagedata fileref="figs/bad-merge-1.png"/></imageobject> +% \caption{A bad merge} + \caption{$B4V0c$C$?%^!<%8(B} + \label{fig:undo:bad-merge-1} +\end{figure} + +%Suppose we have a revision graph like that in +%\ref{fig:undo:bad-merge-1}. What we'd like is to \emph{redo} the merge +%of revisions 2 and 3. + +$B?^(B\ref{fig:undo:bad-merge-1}$B$N$h$&$J%j%S%8%g%s%0%i%U$K$J$C$F$$$k$H$9$k!%(B +$B$3$3$G%j%S%8%g%s(B2$B$H(B3$B$N%^!<%8$r:F$S9T$$$?$$!%(B + +%One way to do so would be as follows. + +$B$=$NJ}K!$N0l$D$O0J2<$N$h$&$K$J$k!%(B + +\begin{enumerate} +% \item Call \hgopt{backout}{--rev=4 --parent=2}. This tells +% \hgcmd{backout} to back out revision 4, which is the bad merge, +% and to when deciding which revision to prefer, to choose parent +% 2, one of the parents of the merge. The effect can be seen in +% \ref{fig:undo:bad-merge-2}. + \item \hgopt{backout}{--rev=4 --parent=2}$B$r<B9T$9$k!%(B\hgcmd{backout}$B$O(B + $BLdBj$N$"$k%^!<%8$G$"$k%j%S%8%g%s(B4$B$r%P%C%/%"%&%H$7!$La$9$Y$-%j%S%8%g(B + $B%s$r7h$a$k:]$K!$N>J}$N?F$N$&$A!$%j%S%8%g%s(B2$B$rA*$V!%7k2L$r?^(B + \ref{fig:undo:bad-merge-2}$B$K<($9!%(B -XXX $BDI5-$NI,MW@-$"$j!%(B\texttt{examples}$B%G%#%l%/%H%jFb$N(B -\texttt{hg-replay}$B%9%/%j%W%H$O5!G=$9$k$,!$%A%'%s%8%;%C%H$N%^!<%8$r07$o$J(B -$B$$!%=EMW$J@)8B$G$"$k!%(B + \begin{figure}[htb] + \centering + \grafix{figs/bad-merge-2} + %<imageobject><imagedata fileref="figs/bad-merge-2.png"/></imageobject> + % \caption{Backing out the merge, favoring one parent} + \caption{$B%^!<%8$r%P%C%/%"%&%H$7!$?F$N0lJ}$rA*$V(B} + \label{fig:undo:bad-merge-2} + \end{figure} + +% \item Call \hgopt{backout}{--rev=4 --parent=3}. This tells +% \hgcmd{backout} to back out revision 4 again, but this time to +% choose parent 3, the other parent of the merge. The result is +% visible in \ref{fig:undo:bad-merge-3}, in which the repository +% now contains three heads. + + \item \hgopt{backout}{--rev=4 --parent=3}$B$r<B9T$9$k!%(B\hgcmd{backout}$B$O$d(B + $B$O$j%j%S%8%g%s(B4$B$r%P%C%/%"%&%H$9$k$,!$:#2s$O%^!<%8$N?F$N$&$A%j%S%8%g(B + $B%s(B3$B$rA*$V!%7k2L$O?^(B\ref{fig:undo:bad-merge-3}$B$N$h$&$K$J$j!$%j%]%8(B + $B%H%j$K$O%X%C%I$,(B3$B$D$G$-$k!%(B + + \begin{figure}[htb] + \centering + \grafix{figs/bad-merge-3} + %<imageobject><imagedata fileref="figs/bad-merge-3.png"/></imageobject> + % \caption{Backing out the merge, favoring the other parent} +% \caption{Backing out the merge, favoring the other parent} + \caption{$B%^!<%8$r%P%C%/%"%&%H$7!$$b$&0lJ}$N?F$rA*$V(B} + \label{fig:undo:bad-merge-3} + \end{figure} + + +% \item Redo the bad merge by merging the two backout heads, +%which reduces the number of heads in the repository to +%two, as can be seen in \ref{fig:undo:bad-merge-4}. + + \item $BLdBj$N$"$C$?%^!<%8$r!$%P%C%/%"%&%H$N7k2L@8$8$?(B2$B$D$N%X%C%I$N4V$G:F(B + $B$S9T$&!%$3$l$K$h$j!$?^(B\ref{fig:undo:bad-merge-4}$B$N$h$&$K%j%]%8%H%j(B + $BFb$N%X%C%I$O(B2$B$D$K$J$k!%(B + + \begin{figure}[htb] + \centering + \grafix{figs/bad-merge-4} + %<imageobject><imagedata fileref="figs/bad-merge-4.png"/></imageobject> +% \caption{Merging the backouts} + \caption{$B%P%C%/%"%&%H7k2L$r%^!<%8$9$k(B} + \label{fig:undo:bad-merge-4} + \end{figure} + +% \item Merge with the commit that was made after the bad merge, as shown +% in \ref{fig:undo:bad-merge-5}. + + \item $B?^(B\ref{fig:undo:bad-merge-5}$B$N$h$&$K!$4V0c$C$?%^!<%8$N8e$K9T$o$l(B + $B$?%3%_%C%H$H%^!<%8$9$k!%(B + + \begin{figure}[htb] + \centering + \grafix{figs/bad-merge-5} + %<imageobject><imagedata fileref="figs/bad-merge-5.png"/></imageobject> + % \caption{Merging the backouts} + \caption{$B%P%C%/%"%&%H$N%^!<%8(B} + \label{fig:undo:bad-merge-5} + \end{figure} + +\end{enumerate} %\subsection{Protect yourself from ``escaped'' changes} @@ -853,16 +961,98 @@ $BCf1{%j%]%8%H%j$N>e$G!$JQ99E~Ce$K%U%C%/$r@_Dj$9$k!J(B\ref{chap:hook}$B$r;2>H!K(B $B$3$H$G!$$"$k<o$N8m$C$?%A%'%s%8%;%C%H$,Cf1{%j%]%8%H%j$K%3%_%C%H$5$l$k$N$r(B -$B<+F0E*$KKI$0$3$H$,$G$-$k!%$=$N$h$&$J@_Dj$r9T$&$3$H$G!$$"$k<o$N8m$C$?%A%'(B -$B%s%8%;%C%H$OCf1{%j%]%8%H%j$KGH5Z$9$k$3$H$,$G$-$:!$;`LG$7$F$$$/798~$,$"(B -$B$k!%9%ET9g$J$3$H$K!$;`LG$OM[$K2pF~$9$kI,MW$J$/5/$-$k!#(B +$B<+F0E*$KKI$0$3$H$,$G$-$k!%@_Dj$r9T$&$3$H$G!$$"$k<o$N8m$C$?%A%'%s%8%;%C%H(B +$B$OCf1{%j%]%8%H%j$KGH5Z$9$k$3$H$,$G$-$:;`LG$7$F$$$/!%9%ET9g$J$3$H$K!$;`LG(B +$B$OM[$K2pF~$9$kI,MW$J$/5/$-$k!#(B %For instance, an incoming change hook that verifies that a changeset %will actually compile can prevent people from inadvertantly ``breaking %the build''. $BNc$($P!$%A%'%s%8%;%C%H$r<B:]$K%3%s%Q%$%k$9$kJQ99E~Ce%U%C%/$O!$ITCm0U$K$h(B -$B$k%S%k%IITG=$rKI$0$3$H$,$G$-$k!%(B +$B$C$F%S%k%IITG=$H$J$k$3$H$rKI$08z2L$,$"$k!%(B + + +%\subsection{What to do about sensitive changes that escape} +\subsection{$B8D?M>pJs$r4^$`%A%'%s%8%;%C%H$NO31L(B} + +%Even a carefully run project can suffer an unfortunate event such as the +%committing and uncontrolled propagation of a file that contains +%important passwords. + +$B%W%m%8%'%/%H$rCm0U?<$/1?1D$7$F$$$F$b!$;~$H$7$F=EMW$J%Q%9%o!<%I$N4^$^$l$?(B +$B%U%!%$%k$N%3%_%C%H$dEAGE$,@8$8$k$3$H$,$"$k!%(B + +%If something like this happens to you, and the information that gets +%accidentally propagated is truly sensitive, your first step should be to +%mitigate the effect of the leak without trying to control the leak +%itself. If you are not 100\% certain that you know exactly who could +%have seen the changes, you should immediately change passwords, cancel +%credit cards, or find some other way to make sure that the information +%that has leaked is no longer useful. In other words, assume that the +%change has propagated far and wide, and that there's nothing more you +%can do. + +$BO31L$,5/$-!$EAGE$7$?>pJs$,6K$a$F=EMW$J>l9g!$$^$:$9$Y$-$3$H$OO31L<+BN$r%3(B +$B%s%H%m!<%k$7$h$&$H$9$k$N$G$O$J$/!$O31L$K$h$k1F6A$rLH$l$k$h$&$K$9$k$3$H$G(B +$B$"$k!%C/$,$3$N>pJs$r8+$?$N$+(B100\%$BL@Gr$G$J$$>l9g$O!$$9$0$K%Q%9%o!<%I$rJQ99(B +$B$7!$>l9g$K$h$C$F$O%/%l%8%C%H%+!<%I$r2rLs$7$?$j!$O31L$7$?>pJs$,L58z$K$J$k(B +$B$h$&$K2DG=$J<j$rBG$D$Y$-$G$"$k!%JL$N8@$$J}$r$9$l$P!$>pJs$O$9$G$KBg$-$JHO(B +$B0O$K9-$^$C$F$*$j!$O31L$7$?>pJs<+BN$K$D$$$F$O$J$9=Q$,$J$$$H2>Dj$9$Y$-$G$"(B +$B$k!%(B + +%You might hope that there would be mechanisms you could use to either +%figure out who has seen a change or to erase the change permanently +%everywhere, but there are good reasons why these are not possible. + +$BJQ99$rH/8+$7$??M$rFCDj$7$?$j!$$"$i$f$k>l=j$GJQ99$r1J5WE*$KJQ99$9$k%a%+%K(B +$B%:%`$,Hw$o$C$F$$$k$N$G$O$J$$$+$H4|BT$9$k8~$-$b$"$k$@$m$&$,!$$3$l$,<!$N$h(B +$B$&$JM}M3$GIT2DG=$G$"$k!%(B + +%Mercurial does not provide an audit trail of who has pulled changes from +%a repository, because it is usually either impossible to record such +%information or trivial to spoof it. In a multi-user or networked +%environment, you should thus be extremely skeptical of yourself if you +%think that you have identified every place that a sensitive changeset +%has propagated to. Don't forget that people can and will send bundles +%by email, have their backup software save data offsite, carry +%repositories on USB sticks, and find other completely innocent ways to +%confound your attempts to track down every copy of a problematic change. + +Mercurial$B$O!$%j%]%8%H%j$+$iC/$,JQ99$r%W%k$7$?$+DI@W$9$k5!9=$r;}$?$J$$!%$J(B +$B$<$J$i$=$N$h$&$J>pJs$r5-O?$9$k$3$H$OIT2DG=$G$"$k$+4JC1$K56$l$k$+$i$G$"(B +$B$k!%=>$C$F!$%^%k%A%f!<%64D6-$d%M%C%H%o!<%/4D6-$G$O!$8D?M>pJs$r4^$`%A%'%s(B +$B%8%;%C%H$,EAGE$7$?HO0O$rFCDj$G$-$k$H9M$($k$Y$-$G$O$J$$!%LdBj$N$"$k%A%'%s(B +$B%8%;%C%H$rDI@W$7$h$&$H$7$?$H$3$m$G!$%A%'%s%8%;%C%H$rF~<j$7$??M!9$O!$(B +\begin{itemize} + \item $B%P%s%I%k$rEE;R%a!<%k$GAw?.$9$k(B + \item $B%5%$%H30$K%G!<%?$rJ]B8$G$-$k%P%C%/%"%C%W%=%U%H%&%'%"$rMQ$$$k(B + \item USB$B%a%b%j$K%j%]%8%H%j$rJ]B8$9$k(B + \item $B$=$l0J30$NM=4|$7$J$$J}K!$rMQ$$$k(B +\end{itemize} +$B$J$I$NJ}K!$G$$$/$i$G$bDI@W$r5=$/$3$H$,2DG=$@$H$$$&$3$H$r3P$($F$*$/$Y$-$@!%(B + +%Mercurial also does not provide a way to make a file or changeset +%completely disappear from history, because there is no way to enforce +%its disappearance; someone could easily modify their copy of Mercurial +%to ignore such directives. In addition, even if Mercurial provided such +%a capability, someone who simply hadn't pulled a ``make this file +%disappear'' changeset wouldn't be affected by it, nor would web crawlers +%visiting at the wrong time, disk backups, or other mechanisms. Indeed, +%no distributed revision control system can make data reliably +%vanish. Providing the illusion of such control could easily give a false +%sense of security, and be worse than not providing it at all. + +Mercurial$B$O%U%!%$%k$d%A%'%s%8%;%C%H$rMzNr$+$i40A4$K>C$75n$k5!G=$rDs6!$7$J(B +$B$$!%$3$l$O>C5n$r6/@)$9$k$3$H$,IT2DG=$G$"$k$3$H$K$h$k!%2>$K$=$N$h$&$J;X<((B +$B$r<BAu$7$?$H$7$F$b!$(BMercurial$B$r2~B$$7$F;X<($rL5;k$9$k$h$&$K$9$k$3$H$OMF0W(B +$B$G$"$k!%$^$?!$(BMercurial$B$,$=$N$h$&$J5!G=$rDs6!$7$?$H$7$F!$(B``$B$3$N%U%!%$%k$r(B +$B>C$;(B''$B$H$$$&%A%'%s%8%;%C%H$r%W%k$7$F$$$J$$%f!<%6$d%?%$%_%s%00-$/%5%$%H$r(B +$BK,Ld$7$?%5!<%A%(%s%8%s$N%/%m!<%i!<!$%G%#%9%/%P%C%/%"%C%W$=$NB>$K$O2?$b1F(B +$B6A$r5Z$\$5$J$$!%<B:]$N$H$3$m!$J,;6%j%S%8%g%s%3%s%H%m!<%k%7%9%F%`$G?.Mj@-(B +$B$N$"$k%G!<%?>CLG5!G=$rDs6!$7$F$$$k$b$N$O$J$$!%$3$N$h$&$J@)8f$,2DG=$@$H$7(B +$B$F$b!$$3$l$OMF0W$K%;%-%e%j%F%#>e$N6<0R$K$J$j!$@)8f5!G=$,0l@Z$J$$>l9g$h$j(B +$B$b?<9o$J>uBV$r0z$-5/$3$9!%(B %\section{Finding the source of a bug} \section{$B%P%0$N860x$r8+$D$1$k(B} @@ -980,17 +1170,19 @@ %to check (the kind of search it performs is called a dichotomic %search). +\hgcmd{bisect}$B$O%W%m%8%'%/%H$N%j%S%8%g%sMzNr$N(B``$B7A>u(B''$B$N>pJs$r!$%5!<%A$9(B +$B$Y$-%A%'%s%8%;%C%H?t$N(B\emph{$BBP?t(B}$B$KHfNc$7$?;~4V$G%5!<%A$9$k$?$a$K;H(B +$B$&!%!JFsJ,C5:w$r9T$&!%!K(B + %With this approach, searching through 10,000 changesets will %take less than three hours, even at ten minutes per test (the search %will require about 14 tests). Limit your search to the last hundred %changesets, and it will take only about an hour (roughly seven tests). -\hgcmd{bisect}$B$O$"$J$?$N%W%m%8%'%/%H$N%j%S%8%g%sMzNr$N(B``$B%7%'%$%W(B''$B$NCN<1(B -$B$r!$%5!<%A$9$Y$-%A%'%s%8%;%C%H?t$N(B\emph{$BBP?t(B}$B$KHfNc$7$?;~4V$G%5!<%A$9$k$?(B -$B$a$K;H$&!%!JFsJ,C5:w$r9T$&!%!K$3$N%"%W%m!<%A$K$h$C$F(B10000$B%A%'%s%8%;%C%H(B -$B$N%5!<%A$O!$3F!9$N%5!<%A$,(B10$BJ,$+$+$C$?$H$7$F$b!$%F%9%H?t$O(B14$B$G(B3$B;~4V0J2<$G(B -$B=*N;$9$k!%:G8e$N(B100$B$N%A%'%s%8%;%C%H$K8B$C$F9T$C$?$H$9$k$H!$$*$h$=(B7$B2s$N(B -$B%F%9%H$G(B1$B;~4VDxEY$G=*N;$9$k!%(B +$B$3$N%"%W%m!<%A$K$h$j!$(B10000$B$N%A%'%s%8%;%C%H$KBP$9$k%5!<%A$O!$%5!<%A0l2s$"(B +$B$?$j(B10$BJ,$+$+$C$?$H$7$F$b(B3$B;~4V0J2<$G=*N;$9$k!%%F%9%H2s?t$O(B14$B2s$H$J$k!%:G8e(B +$B$N(B100$B$N%A%'%s%8%;%C%H$K8BDj$9$k$J$i$P!$%F%9%H$O$*$h$=(B1$B;~4VDxEY$G=*N;$7!$(B +$B%F%9%H2s?t$O(B7$B2s$H$J$k!%(B %The \hgcmd{bisect} command is aware of the ``branchy'' nature of a %Mercurial project's revision history, so it has no problems dealing @@ -1053,7 +1245,7 @@ %\item You run your binary test. % \begin{itemize} % \item If the test succeeded, you tell \hgcmd{bisect} by running the -% \hgcmdargs{bisect}{good} command. +% \hgcmdargs{bisect}{--good} command. % \item If it failed, run the \hgcmdargs{bisect}{--bad} command. % \end{itemize} %\item The command uses your information to decide which changeset to @@ -1069,7 +1261,7 @@ \begin{enumerate} \item $B%P%$%J%j%F%9%H$r<B9T$9$k(B \begin{itemize} - \item $B%F%9%H$,@.8y$7$?>l9g!$(B\hgcmd{bisect}$B$r0z?t(B\hgcmdargs{bisect}{good} + \item $B%F%9%H$,@.8y$7$?>l9g!$(B\hgcmd{bisect}$B$r0z?t(B\hgcmdargs{bisect}{--good} $B$rIU$1$F<B9T$9$k!%(B \item $B%F%9%H$,<:GT$7$?>l9g$O(B\hgcmdargs{bisect}{--bad}$B%3%^%s%I$r<B9T$9(B $B$k!%(B @@ -1187,18 +1379,18 @@ \subsection{$B%5!<%A8e$N%/%j!<%s%"%C%W(B} %When you're finished using the \hgcmd{bisect} command in a -%repository, you can use the \hgcmdargs{bisect}{reset} command to drop +%repository, you can use the \hgcmdargs{bisect}{--reset} command to drop %the information it was using to drive your search. The command %doesn't use much space, so it doesn't matter if you forget to run this %command. However, \hgcmd{bisect} won't let you start a new search in -%that repository until you do a \hgcmdargs{bisect}{reset}. +%that repository until you do a \hgcmdargs{bisect}{--reset}. %\interaction{bisect.search.reset} $B%j%]%8%H%jFb$G(B\hgcmd{bisect}$B%3%^%s%I$r;H$$=*$C$?8e$K(B -\hgcmdargs{bisect}{reset}$B%3%^%s%I$GC5:w$K;H$C$?>pJs$r>C5n$9$k$3$H$,$G$-(B +\hgcmdargs{bisect}{--reset}$B%3%^%s%I$GC5:w$K;H$C$?>pJs$r>C5n$9$k$3$H$,$G$-(B $B$k!%%3%^%s%I$OBg$-$J%9%Z!<%9$r;H$&$o$1$G$O$J$$$N$G!$$3$N%3%^%s%I$r<B9T$9(B $B$k$N$rK:$l$F$bFC$KLdBj$O$J$$!%$7$+$7(B\hgcmd{bisect}$B$O(B -\hgcmdargs{bisect}{reset}$B$,<B9T$5$l$k$^$G!$$=$N%j%]%8%H%jFb$G?7$?$JC5:w(B +\hgcmdargs{bisect}{--reset}$B$,<B9T$5$l$k$^$G!$$=$N%j%]%8%H%jFb$G?7$?$JC5:w(B $B$r;O$a$k$3$H$O$G$-$J$$!%(B \interaction{bisect.search.reset} @@ -1331,7 +1523,6 @@ $B$j!$$"$k%A%'%s%8%;%C%H$r(B\hgcmdargs{bisect}{--skip}$B$K$h$C$FL$%F%9%H$H%^!<(B $B%/$9$k$3$H$,$G$-$k!%(B - %A different problem could arise if your test for a bug's presence is %not specific enough. If you check for ``my program crashes'', then %both your crashing bug and an unrelated crashing bug that masks it @@ -1342,7 +1533,6 @@ $B$H!$$=$l$H$OL54X78$J%/%i%C%7%e%P%0$,:.:_$F$$$k$H$3$l$i$OF1$8$K8+$($F$7$^(B $B$$!$7k2LE*$K%A%'%C%/$r%^%9%/$7$F$7$^$$!$(B\hgcmd{bisect}$B$r%_%9%j!<%I$9$k!%(B - %Another useful situation in which to use \hgcmdargs{bisect}{--skip} is %if you can't test a revision because your project was in a broken and %hence untestable state at that revision, perhaps because someone @@ -1387,7 +1577,7 @@ $BBP$7$F$b>/?t$N%F%9%H$rDI2C$9$k$@$1$G:Q$`!%(B -%%% Local Variables: +%%% Local Variables: %%% mode: yatex %%% TeX-master: "00book" -%%% End: +%%% End: