Mercurial > hgbook
view ja/daily.tex @ 387:1604f2b2054b
more intro.tex
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Sun, 22 Feb 2009 00:48:17 +0900 |
parents | 38f034c1da53 |
children | de4142983445 |
line wrap: on
line source
%\chapter{Mercurial in daily use} \chapter{Mercurial$B$G$NF|>o:n6H(B} \label{chap:daily} %\section{Telling Mercurial which files to track} \section{$BDI@W$9$Y$-%U%!%$%k$N(BMercurial$B$X$NEPO?(B} %Mercurial does not work with files in your repository unless you tell %it to manage them. The \hgcmd{status} command will tell you which %files Mercurial doesn't know about; it uses a ``\texttt{?}'' to %display such files. Mercurial$B$O!$%f!<%6$K$h$k%U%!%$%k4IM}$N;X<($,$J$$8B$j!$%j%]%8%H%jFb$N%U%!(B $B%$%k$G$"$C$F$b4IM}$r9T$o$J$$!%(BMercurial$B$,4IM}$7$J$$%U%!%$%k$O(B \hgcmd{status}$B%3%^%s%I$r<B9T$9$k$H(B``\texttt{?}''$B$HI=<($5$l$k!%(B %To tell Mercurial to track a file, use the \hgcmd{add} command. Once %you have added a file, the entry in the output of \hgcmd{status} for %that file changes from ``\texttt{?}'' to ``\texttt{A}''. %\interaction{daily.files.add} Mercurial$B$K%U%!%$%k$NDI@W$r$5$;$k$K$O!$(B\hgcmd{add}$B%3%^%s%I$rMQ$$$k!%0lEY(B $B%U%!%$%k$rDI2C$9$k$H!$(B\hgcmd{status}$B%3%^%s%I$N=PNO$O(B``\texttt{?}''$B$+$i(B ``\texttt{A}''$B$KJQ$o$k!%(B \interaction{daily.files.add} %After you run a \hgcmd{commit}, the files that you added before the %commit will no longer be listed in the output of \hgcmd{status}. The %reason for this is that \hgcmd{status} only tells you about %``interesting'' files---those that you have modified or told Mercurial %to do something with---by default. If you have a repository that %contains thousands of files, you will rarely want to know about files %that Mercurial is tracking, but that have not changed. (You can still %get this information; we'll return to this later.) \hgcmd{commit}$B%3%^%s%I$r<B9T$9$k$H!$(Bcommit$B$NA0$KDI2C$7$?%U%!%$%k$O(B \hgcmd{status}$B$N=PNO$K8=$l$J$/$J$k!%$3$l$O!$(B\hgcmd{status}$B$,%G%U%)%k%H$G(B $B$OJQ99$r2C$($?$j!$(BMercurial$B$K2?$+$r$5$;$?$H$$$C$?(B``$BCmL\$9$Y$-(B''$B%U%!%$%k$N(B $B$_$rI=<($9$k$?$a$G$"$k!%?t@i$N%U%!%$%k$+$i$J$k%j%]%8%H%j$N>l9g!$(BMercurial$B$,(B $BDI@W$7$F$$$k$b$N$N!$JQ99$N2C$($i$l$F$$$J$$%U%!%$%k$K$D$$$F2?$+$rCN$j$?$$(B $B$H$$$&$3$H$O5)$G$"$k!%!J$b$A$m$sCN$j$?$$>l9g$O>pJs$rF@$k$3$H$b$G$-$k!%$3(B $B$l$K$D$$$F$O8e=R$9$k!%!K(B %Once you add a file, Mercurial doesn't do anything with it %immediately. Instead, it will take a snapshot of the file's state the %next time you perform a commit. It will then continue to track the %changes you make to the file every time you commit, until you remove %the file. $BDI2C$7$?%U%!%$%k$KBP$7$F(BMercurial$B$,D>$A$K9T$&$3$H$O2?$b$J$$$,!$$=$NBe$o$j(B $B$K<!2s$N%3%_%C%H;~$K%U%!%$%k>uBV$N%9%J%C%W%7%g%C%H$r<h$k!%$=$7$F%U%!%$%k(B $B$r:o=|$9$k$^$G%3%_%C%HKh$K%U%!%$%k$NJQ2=$rDI@W$9$k!%(B %\subsection{Explicit versus implicit file naming} \subsection{$BL@<(E*$J%U%!%$%kL?L>BP0EL[$N%U%!%$%kL?L>(B} %A useful behaviour that Mercurial has is that if you pass the name of %a directory to a command, every Mercurial command will treat this as %``I want to operate on every file in this directory and its %subdirectories''. %\interaction{daily.files.add-dir} %Notice in this example that Mercurial printed the names of the files %it added, whereas it didn't do so when we added the file named %\filename{a} in the earlier example. Mercurial$B$NA4$F$N%3%^%s%I$O!$0z?t$H$7$F%G%#%l%/%H%jL>$rEO$9$H!$%G%#%l%/%H(B $B%j$NFb$NA4$F$N%U%!%$%k$H%5%V%G%#%l%/%H%j$KBP$9$kA`:n$G$"$k$H2r<a$9$k$?$a(B $BJXMx$G$"$k!%(B \interaction{daily.files.add-dir} $B$3$NNc$G$O(BMercurial$B$ODI2C$7$?%U%!%$%kL>$rI=<($7$F$$$k$,!$A0$NNc$G(B \filename{a}$B$H$$$&L>A0$N%U%!%$%k$rDI2C$7$?:]$K$OI=<($7$F$$$J$+$C$?E@$KCm(B $B0U$5$l$?$$!%(B %What's going on is that in the former case, we explicitly named the %file to add on the command line, so the assumption that Mercurial %makes in such cases is that you know what you were doing, and it %doesn't print any output. $BA0$NNc$G$O%3%^%s%I%i%$%s$G$I$N%U%!%$%k$rDI2C$9$k$N$+$rL@<(E*$K;XDj$7$?$?(B $B$a!$(BMercurial$B$O%f!<%6$,2?$r$7$h$&$H$7$F$$$k$N$+J,$+$C$F$$$k$H?dDj$7$F2?$b(B $BI=<($7$J$+$C$?!%(B %However, when we \emph{imply} the names of files by giving the name of %a directory, Mercurial takes the extra step of printing the name of %each file that it does something with. This makes it more clear what %is happening, and reduces the likelihood of a silent and nasty %surprise. This behaviour is common to most Mercurial commands. $B$7$+$7%G%#%l%/%H%jL>$rM?$($k$3$H$G%U%!%$%kL>$r0EL[E*$KM?$($?>l9g!"(B Mercurial$B$O4XO"$9$k%U%!%$%k$NL>A0$r(B1$B$D$:$DI=<($9$kDI2C$N%9%F%C%W$rF'$`!%(B $B$3$l$K$h$C$F2?$,5/$3$C$F$$$k$N$+M}2r$7$d$9$/$9$k$H6&$K!$D@L[N"$KLq2p$JLd(B $BBj$,5/$3$k2DG=@-$r8:$i$7$F$$$k!%$3$N5sF0$O(BMercurial$B$NBgH>$N%3%^%s%I$K6&(B $BDL$7$F$$$k!%(B %\subsection{Aside: Mercurial tracks files, not directories} \subsection{$B$3$\$lOC(B: Mercurial$B$O%G%#%l%/%H%j$G$O$J$/%U%!%$%k$rDI@W$9$k(B} %Mercurial does not track directory information. Instead, it tracks %the path to a file. Before creating a file, it first creates any %missing directory components of the path. After it deletes a file, it %then deletes any empty directories that were in the deleted file's %path. This sounds like a trivial distinction, but it has one minor %practical consequence: it is not possible to represent a completely %empty directory in Mercurial. Mercurial$B$O%G%#%l%/%H%j>pJs$rDI@W$7$J$$!%$=$NBe$o$j!$%U%!%$%k$X$N%Q%9$rDI(B $B@W$7$F$$$k!%%U%!%$%k$r:n@.$9$k:]$K$O!$$^$:%Q%9$N%G%#%l%/%H%jItJ,$rJd40$9(B $B$k!%%U%!%$%k$r>C5n$7$?8e$O!$%U%!%$%k$N4^$^$l$F$$$?6u$N%G%#%l%/%H%j$rA4$F(B $B>C5n$9$k!%$3$l$OEvA3$N5sF0$N$h$&$K8+$($k$,!$<B:]>e$O>.$5$JLdBj$r0z$-5/$3(B $B$9!%$9$J$o$A!$(BMercurial$B$O40A4$K6u$N%G%#%l%/%H%j$rI=8=$9$k$3$H$,$G$-$J$$$N(B $B$G$"$k!%(B %Empty directories are rarely useful, and there are unintrusive %workarounds that you can use to achieve an appropriate effect. The %developers of Mercurial thus felt that the complexity that would be %required to manage empty directories was not worth the limited benefit %this feature would bring. $B6u$N%G%#%l%/%H%j$,M-MQ$G$"$k$3$H$OLGB?$K$J$$$,!$E,Ev$J%o!<%/%"%i%&%s%I$H(B $B$7$F!$%j%]%8%H%j$NF0$-$rK8$2$J$$J}K!$,B8:_$9$k!%(B Mercurial$B$N3+H/<T$?$A$O!$6u$N%G%#%l%/%H%j$rI=8=$9$k$?$a$K2C$o$kJ#;($5$O!$$=(B $B$N5!G=$K8+9g$o$J$$$H9M$($?!%(B %If you need an empty directory in your repository, there are a few %ways to achieve this. One is to create a directory, then \hgcmd{add} a %``hidden'' file to that directory. On Unix-like systems, any file %name that begins with a period (``\texttt{.}'') is treated as hidden %by most commands and GUI tools. This approach is illustrated in %figure~\ref{ex:daily:hidden}. $B%j%]%8%H%j$K6u$N%G%#%l%/%H%j$,I,MW$J>l9g!$$3$l$r<B8=$9$kJ}K!$,$$$/$D$+$"(B $B$k!%(B1$B$DL\$O!$$^$:%G%#%l%/%H%j$r:n@.$7!$1#$7%U%!%$%k$r$3$N%G%#%l%/%H%jFb$K(B \hgcmd{add}$B$9$k!%(BUnix$B7O%7%9%F%`$G$O!$%T%j%*%I(B(``\texttt{.}'')$B$G;O$^$k%U%!(B $B%$%k$OBgH>$N%3%^%s%I$H(BGUI$B%D!<%k$G1#$7%U%!%$%k$H$7$F<h$j07$o$l$k!%(B $B>\:Y$K$D$$$F$O?^(B~\ref{ex:daily:hidden}$B$r;2>H$5$l$?$$!%(B \begin{figure}[ht] \interaction{daily.files.hidden} % \caption{Simulating an empty directory using a hidden file} \caption{$B1#$7%U%!%$%k$r;H$C$F6u$N%G%#%l%/%H%j$r%7%_%e%l!<%H$9$k(B} \label{ex:daily:hidden} \end{figure} %Another way to tackle a need for an empty directory is to simply %create one in your automated build scripts before they will need it. $B6u$N%G%#%l%/%H%j$r07$&JL$NJ}K!$K$O!$<+F0%S%k%I%9%/%j%W%H$NCf$G!$I,MW$K$J$k(B $BA0$K:n@.$9$k$3$H$,$"$k!%(B %\section{How to stop tracking a file} \section{$B%U%!%$%kDI@W$NDd;_(B} %Once you decide that a file no longer belongs in your repository, use %the \hgcmd{remove} command; this deletes the file, and tells Mercurial %to stop tracking it. A removed file is represented in the output of %\hgcmd{status} with a ``\texttt{R}''. %\interaction{daily.files.remove} $B%U%!%$%k$,%j%]%8%H%j$KI,MW$J$/$J$C$?;~$O(B\hgcmd{remove}$B%3%^%s%I$r<B9T$9(B $B$k!%$3$N%3%^%s%I$O%U%!%$%k$r:o=|$7$?>e$G(BMercurial$B$K%U%!%$%kDI@W$NDd;_$r;X(B $B<($9$k!%:o=|$5$l$?%U%!%$%k$O(B\hgcmd{status}$B%3%^%s%I$N=PNO$G(B``\texttt{R}'' $B$HI=<($5$l$k!%(B \interaction{daily.files.remove} %After you \hgcmd{remove} a file, Mercurial will no longer track %changes to that file, even if you recreate a file with the same name %in your working directory. If you do recreate a file with the same %name and want Mercurial to track the new file, simply \hgcmd{add} it. %Mercurial will know that the newly added file is not related to the %old file of the same name. $B0lEY%U%!%$%k$r(B\hgcmd{remove}$B$7$?8e$G$O!$(BMercurial$B$O%o!<%-%s%0%G%#%l%/%H%j(B $BFb$K$?$H$(F1$8L>A0$G%U%!%$%k$,:F@8@.$5$l$F$b%U%!%$%k$X$NJQ99$rDI@W$7$J$$!%(B $B%U%!%$%k$r:F@8@.$7!$(BMercurial$B$KDI@W$5$;$?$$$N$G$"$l$P!$(B\hgcmd{add}$B$r9T$&!%(B Mercurial$B$O!$?75,$KDI2C$5$l$?%U%!%$%k$rF1L>$N8E$$%U%!%$%k$H4X78$J$/07$&!%(B %\subsection{Removing a file does not affect its history} \subsection{$B%U%!%$%k:o=|$OMzNr$K1F6A$rM?$($J$$(B} %It is important to understand that removing a file has only two %effects. $B%U%!%$%k$N:o=|$,%j%]%8%H%j$KM?$($k1F6A$O(B2$B$D$N$_$G$"$k!%(B \begin{itemize} %\item It removes the current version of the file from the working % directory. \item $B%o!<%-%s%0%G%#%l%/%H%j$+$i869F$N%P!<%8%g%s$N%U%!%$%k$r>C5n$9$k!%(B %\item It stops Mercurial from tracking changes to the file, from the % time of the next commit. \item $B:o=|$9$k%U%!%$%k$X$NJQ99$r<!2s$N%3%_%C%H$+$i(BMercurial$B$,DI@W$7$J$$(B $B$h$&$K$9$k!%(B \end{itemize} %Removing a file \emph{does not} in any way alter the \emph{history} of %the file. $B%U%!%$%k$r$I$N$h$&$K:o=|$7$F$b%U%!%$%k$N(B\emph{$BMzNr(B}$B$OJQ99(B\emph{$B$5$l$J$$(B}$B!%(B %If you update the working directory to a changeset in which a file %that you have removed was still tracked, it will reappear in the %working directory, with the contents it had when you committed that %changeset. If you then update the working directory to a later %changeset, in which the file had been removed, Mercurial will once %again remove the file from the working directory. $B%o!<%-%s%0%G%#%l%/%H%j$r!$>C5n$7$?%U%!%$%k$r4^$`%A%'%s%8%;%C%H$K99?7$9$k(B $B$H!$%U%!%$%k$O$=$N%A%'%s%8%;%C%H$G$NFbMF$G:F$S%o!<%-%s%0%G%#%l%/%H%j$K8=(B $B$l$k!%$=$3$G%U%!%$%k$,>C5n$5$l$F$$$k8e$N%A%'%s%8%;%C%H$K99?7$9$k(B $B$H!$(BMercurial$B$O%U%!%$%k$r:F$S%o!<%-%s%0%G%#%l%/%H%j$+$i>C5n$9$k!%(B %\subsection{Missing files} \subsection{$B7gMn$7$?%U%!%$%k(B} %Mercurial considers a file that you have deleted, but not used %\hgcmd{remove} to delete, to be \emph{missing}. A missing file is %represented with ``\texttt{!}'' in the output of \hgcmd{status}. %Mercurial commands will not generally do anything with missing files. %\interaction{daily.files.missing} Mercurial$B$O!$(B\hgcmd{remove}$B$r;H$o$:$K>C5n$5$l$?%U%!%$%k$r(B\emph{$B7gMn(B}$B$7$?(B $B%U%!%$%k$H$7$F07$&!%7gMn%U%!%$%k$O(B\hgcmd{status}$B%3%^%s%I$N=PNO$G(B ``\texttt{!}''$B$HI=<($5$l$k!%(BMercurial$B$N%3%^%s%I$O!$DL>o!$7gMn$7$?%U%!%$(B $B%k$K$O2?$b9T$o$J$$!%(B \interaction{daily.files.missing} %If your repository contains a file that \hgcmd{status} reports as %missing, and you want the file to stay gone, you can run %\hgcmdargs{remove}{\hgopt{remove}{--after}} at any time later on, to %tell Mercurial that you really did mean to remove the file. %\interaction{daily.files.remove-after} $B%j%]%8%H%jFb$G(B\hgcmd{status}$B%3%^%s%I$,7gMn$H%j%]!<%H$9$k%U%!%$%k$,$"$k>l(B $B9g!$(B\hgcmdargs{remove}{\hgopt{remove}{--after}}$B$r<B9T$7$F!$(BMercurial$B$K7g(B $BMn%U%!%$%k$,>C5n$5$l$?$b$N$G$"$k$3$H$r;X<($9$k$3$H$,$G$-$k!%(B \interaction{daily.files.remove-after} %On the other hand, if you deleted the missing file by accident, use %\hgcmdargs{revert}{\emph{filename}} to recover the file. It will %reappear, in unmodified form. %\interaction{daily.files.recover-missing} $B0lJ}$G!$8m$C$F%U%!%$%k$r>C5n$7$?>l9g!$(B\hgcmdargs{revert}{\emph{filename}}$B$r(B $B<B9T$9$k$3$H$G%U%!%$%k$r=$I|$9$k$3$H$,$G$-$k!%%U%!%$%k$O2?$bJQ99$5$l$J$$>uBV(B $B$G=$I|$5$l$k!%(B \interaction{daily.files.recover-missing} %\subsection{Aside: why tell Mercurial explicitly to remove a file?} \subsection{$B$3$\$lOC(B: $B$J$<(BMercurial$B$X%U%!%$%k$N:o=|$rL@<(E*$K;X<($7$J$1(B $B$l$P$J$i$J$$$+(B} %You might wonder why Mercurial requires you to explicitly tell it that %you are deleting a file. Early during the development of Mercurial, %it let you delete a file however you pleased; Mercurial would notice %the absence of the file automatically when you next ran a %\hgcmd{commit}, and stop tracking the file. In practice, this made it %too easy to accidentally remove a file without noticing. $B$J$<(BMercurial$B$K%U%!%$%k$N:o=|$rL@<(E*$K;X<($7$J$1$l$P$J$i$J$$$N$@$m$&$+!)(B Mercurial$B$N3+H/$N=i4|$K$O!$%U%!%$%k$,$J$$$3$H$r8!CN$9$k$H!$<!$K(B \hgcmd{commit}$B$,<B9T$5$l$k;~$K<+F0E*$K%U%!%$%k$NDI@W$r$d$a$F$$$?!%<B:]$K(B $B;H$C$F$_$k$H$3$NF0:n$G$O%U%!%$%k$rCN$i$:$N$&$A$K<:$&$3$H$,IQH/$7$?$N$G$"(B $B$k!%(B %\subsection{Useful shorthand---adding and removing files in one step} \subsection{$BLr$KN)$D4JN,K!(B---$B%U%!%$%k$NDI2C$H:o=|$r(B1$B%9%F%C%W$G9T$&(B} %Mercurial offers a combination command, \hgcmd{addremove}, that adds %untracked files and marks missing files as removed. %\interaction{daily.files.addremove} %The \hgcmd{commit} command also provides a \hgopt{commit}{-A} option %that performs this same add-and-remove, immediately followed by a %commit. %\interaction{daily.files.commit-addremove} Mercurial$B$O(B\hgcmd{addremove}$B$H$$$&AH$_9g$o$;%3%^%s%I$r;}$C$F$$$k!%$3$N%3(B $B%^%s%I$ODI@W$5$l$F$$$J$$%U%!%$%k72$rDI2C$7!$7gMn$7$F$$$k%U%!%$%k$r>C5n$5(B $B$l$?$H%^!<%/$9$k!%(B \interaction{daily.files.addremove} \hgcmd{commit}$B%3%^%s%I$K$O(B\hgopt{commit}{-A}$B%*%W%7%g%s$,$"$j!$F1$8DI2C$H(B $B:o=|$NA`:n$r%3%_%C%HD>8e$K9T$&!%(B \interaction{daily.files.commit-addremove} %\section{Copying files} \section{$B%U%!%$%k$N%3%T!<(B} %Mercurial provides a \hgcmd{copy} command that lets you make a new %copy of a file. When you copy a file using this command, Mercurial %makes a record of the fact that the new file is a copy of the original %file. It treats these copied files specially when you merge your work %with someone else's. Mercurial$B$K$O!$%U%!%$%k$N?7$7$$%3%T!<$r:n$k(B\hgcmd{copy}$B%3%^%s%I$,$"$k!%(B $B$3$N%3%^%s%I$r;H$C$F%U%!%$%k$r%3%T!<$9$k$H!$(BMercurial$B$O?7$7$$%U%!%$%k$,(B $B%*%j%8%J%k$NJ#@=$G$"$k$3$H$r5-O?$9$k!%J#@=$5$l$?%U%!%$%k$O!$JL$N?M$K$h$k(B $BJQ99$r%^!<%8$9$k;~$KFCJL$J<h$j07$$$,$J$5$l$k!%(B %\subsection{The results of copying during a merge} \subsection{$B%^!<%8Cf$N%3%T!<$N7k2L(B} %What happens during a merge is that changes ``follow'' a copy. To %best illustrate what this means, let's create an example. We'll start %with the usual tiny repository that contains a single file. %\interaction{daily.copy.init} %We need to do some work in parallel, so that we'll have something to %merge. So let's clone our repository. %\interaction{daily.copy.clone} %Back in our initial repository, let's use the \hgcmd{copy} command to %make a copy of the first file we created. %\interaction{daily.copy.copy} $B%^!<%8Cf$K$O!$%3%T!<$K(B``$B=>$&(B''$B$3$H$,5/$-$k!%$3$l$N0UL#$9$k$H$3$m$r<($9$?(B $B$a$K!$Nc$r5s$2$k$3$H$K$9$k!%$$$D$b$N$h$&$K!$%U%!%$%k(B1$B$D$@$1$r4^$`>.$5$J%j(B $B%]%8%H%j$r:n@.$9$k!%(B \interaction{daily.copy.init} $B%^!<%8$9$Y$-FbMF$r:n$k$?$a$KJB9T$7$F$$$/$D$+$N:n6H$r9T$&I,MW$,$"$k$N$G!$(B $B%j%]%8%H%j$N%/%m!<%s$r9T$&!%(B \interaction{daily.copy.clone} $B:G=i$N%j%]%8%H%j$KLa$C$F!$(B\hgcmd{copy}$B%3%^%s%I$r;H$C$F!$:n@.$7$?%U%!%$%k(B $B$N%3%T!<$r9T$&!%(B \interaction{daily.copy.copy} %If we look at the output of the \hgcmd{status} command afterwards, the %copied file looks just like a normal added file. %\interaction{daily.copy.status} %But if we pass the \hgopt{status}{-C} option to \hgcmd{status}, it %prints another line of output: this is the file that our newly-added %file was copied \emph{from}. %\interaction{daily.copy.status-copy} $B$=$N8e$G(B\hgcmd{status}$B%3%^%s%I$N=PNO$r8+$k$H%3%T!<$5$l$?%U%!%$%k$ODL>oDL(B $B$j$KDI2C$5$l$?%U%!%$%k$H$7$F8+$($k!%(B \interaction{daily.copy.status} $B$7$+$7(B\hgcmd{status}$B%3%^%s%I$K(B\hgopt{status}{-C}$B%*%W%7%g%s$rEO$9$H!$?7$?(B $B$KDI2C$5$l$?%U%!%$%k$,(B\emph{$B$I$N(B}$B%U%!%$%k$+$i%3%T!<$5$l$?$N$+$r<($99T$,(B $B=PNO$5$l$k!%(B \interaction{daily.copy.status-copy} %Now, back in the repository we cloned, let's make a change in %parallel. We'll add a line of content to the original file that we %created. %\interaction{daily.copy.other} %Now we have a modified \filename{file} in this repository. When we %pull the changes from the first repository, and merge the two heads, %Mercurial will propagate the changes that we made locally to %\filename{file} into its copy, \filename{new-file}. %\interaction{daily.copy.merge} $B$3$3$G%/%m!<%s$7$?%j%]%8%H%j$K$bJQ99$r2C$($k!%:n@.$7$?%U%!%$%k$K0l9T$rDI(B $B2C$9$k!%(B \interaction{daily.copy.other} $B$3$l$G$3$N%j%]%8%H%j$K$bJQ99$5$l$?(B\filename{file}$B$,B8:_$9$k$3$H$K$J(B $B$k!%$3$3$G:G=i$N%j%]%8%H%j$+$iJQ99$r(Bpull$B$7!$(B2$B$D$N(Bhead$B$r%^!<%8$9$k$H(B Mercurial$B$O%m!<%+%k$J(B\filename{file}$B$KBP$9$kJQ99$r$=$N%3%T!<(B \filename{new-file}$B$KGH5Z$5$;$k!%(B \interaction{daily.copy.merge} %\subsection{Why should changes follow copies?} \subsection{$BJQ99$O$J$<%3%T!<$K=>$o$J$1$l$P$J$i$J$$$+(B} \label{sec:daily:why-copy} %This behaviour, of changes to a file propagating out to copies of the %file, might seem esoteric, but in most cases it's highly desirable. $B%U%!%$%k$X$NJQ99$,$=$N%3%T!<$XGH5Z$9$kF0:n$OFq2r$K;W$($k$+$b$7$J$$$,!$B?(B $B$/$N>l9g$OHs>o$KK>$^$7$$F0:n$G$"$k!%(B %First of all, remember that this propagation \emph{only} happens when %you merge. So if you \hgcmd{copy} a file, and subsequently modify the %original file during the normal course of your work, nothing will %happen. $B$^$:Bh0l$K$3$NGH5Z$O%^!<%8$r9T$&$H$-$K(B\emph{$B$N$_(B}$BH/@8$9$k!%=>$C$F%U%!%$%k(B $B$r(B\hgcmd{copy}$B$9$k>l9g$d!$DL>o$N:n6H$G%*%j%8%J%k%U%!%$%k$rJQ99$9$k>l9g$O(B $B2?$b5/$-$J$$!%(B %The second thing to know is thatmodifications will only propagate %across a copy as long as the repository that you're pulling changes %from \emph{doesn't know} about the copy. $BCN$C$F$*$/$Y$-E@$N(B2$B$DL\$O!$JQ99$r(Bpull$B$9$k%j%]%8%H%j$,!$%3%T!<$K$D$$$F(B \emph{$B4XCN$7$J$$(B}$B8B$j!$JQ99$OGH5Z$9$k$H$$$&$3$H$G$"$k!%(B %The reason that Mercurial does this is as follows. Let's say I make %an important bug fix in a source file, and commit my changes. %Meanwhile, you've decided to \hgcmd{copy} the file in your repository, %without knowing about the bug or having seen the fix, and you have %started hacking on your copy of the file. Mercurial$B$,$3$N$h$&$KF0:n$9$kM}M3$r@bL@$9$k!%:#!$;d$,=EMW$J%P%0=$@5$r(B1$B$D(B $B$N%=!<%9%U%!%$%k$K$D$$$F9T$$!$JQ99$r%3%_%C%H$7$?$H$9$k!%$=$N4V!$$"$J$?$O(B $B<+J,$N%j%]%8%H%j$NCf$G!$$=$N%P%0$"$k$$$O=$@5$rCN$i$:!$$=$N%U%!%$%k$N(B \hgcmd{copy}$B$r9T$$!$%U%!%$%k$NJQ99$r;O$a$?$H$9$k!%(B %If you pulled and merged my changes, and Mercurial \emph{didn't} %propagate changes across copies, your source file would now contain %the bug, and unless you remembered to propagate the bug fix by hand, %the bug would \emph{remain} in your copy of the file. $B$"$J$?$,;d$N9T$C$?JQ99$r(Bpull$B$7!$(Bmerge$B$7$?>l9g!$(BMercurial$B$OJQ99$r%3%T!<4V(B $B$GGH5Z$5$;$J$$!%$"$J$?$N%=!<%9%U%!%$%k:#%P%0$r;}$C$F$$$k$+$b$7$l$J$$$,!$(B $B%P%0=$@5$r<j$GGH5Z$5$;$J$1$l$P%P%0$O%U%!%$%k$N%3%T!<$K(B\emph{$B;D$k(B}$B!%(B %By automatically propagating the change that fixed the bug from the %original file to the copy, Mercurial prevents this class of problem. %To my knowledge, Mercurial is the \emph{only} revision control system %that propagates changes across copies like this. $B%P%0$r=$@5$9$kJQ99$r<+F0E*$K%*%j%8%J%k%U%!%$%k$+$i%3%T!<$XGH5Z$5$;$k$3$H(B $B$K$h$C$F!$(BMercurial$B$O$3$NN`$NLdBj$rHr$1$F$$$k!%;d$NCN$k8B(B $B$j!$(BMercurial$B$O!$$3$N$h$&$J%3%T!<4V$GJQ99$rGH5Z$5$;$kM#0l$N%j%S%8%g%s%3%s(B $B%H%m!<%k%7%9%F%`$G$"$k!%(B %Once your change history has a record that the copy and subsequent %merge occurred, there's usually no further need to propagate changes %from the original file to the copied file, and that's why Mercurial %only propagates changes across copies until this point, and no %further. $B%3%T!<$H8eB3$N%^!<%8$,5/$3$C$?$3$H$,99?7MzNr$K4^$^$l$k>l9g!$JQ99$r%*%j%8(B $B%J%k%U%!%$%k$+$i%3%T!<$5$l$?%U%!%$%k$X$5$i$KGH5Z$5$;$kI,MW$O$J$$!%$3$l$,(B Mercurial$B$,$3$N;~E@$^$G$N$_JQ99$r%3%T!<4V$GGH5Z$5$;!$$=$N8e$G$O9T$o$J$$M}(B $BM3$G$"$k!%(B %\subsection{How to make changes \emph{not} follow a copy} \subsection{$BJQ99$,%3%T!<$K=>$o$J$$$h$&$K$9$kJ}K!(B} %If, for some reason, you decide that this business of automatically %propagating changes across copies is not for you, simply use your %system's normal file copy command (on Unix-like systems, that's %\command{cp}) to make a copy of a file, then \hgcmd{add} the new copy %by hand. Before you do so, though, please do reread %section~\ref{sec:daily:why-copy}, and make an informed decision that %this behaviour is not appropriate to your specific case. $B2?$i$+$NM}M3$G$3$N$h$&$KJQ99$,<+F0E*$KGH5Z$9$k$d$jJ}$,9%$^$7$/$J$$$H;W$o(B $B$l$k>l9g$O!$%7%9%F%`I8=`$N$"%U%!%$%k%3%T!<%3%^%s%I!J(BUNIX$B7O%7%9%F%`$G$O(B \command{cp}$B!K$r;H$C$F%U%!%$%k$N%3%T!<$r9T$$!$(B\hgcmd{add}$B$G?7$7$$%3%T!<$r(B $B<jF0$GDI2C$9$k$3$H$,$G$-$k!%$3$l$r<B:]$K9T$&A0(B $B$K!$(B~\ref{sec:daily:why-copy}$B@a$r:FFI$7!$$3$N$d$jJ}$N>\:Y$rF'$^$($?>e$G!$(B $B$"$J$?$N%1!<%9$KE,$7$F$$$k$+H=CG$7$F$[$7$$!%(B %\subsection{Behaviour of the \hgcmd{copy} command} \subsection{\hgcmd{copy}$B%3%^%s%I$N5sF0(B} %When you use the \hgcmd{copy} command, Mercurial makes a copy of each %source file as it currently stands in the working directory. This %means that if you make some modifications to a file, then \hgcmd{copy} %it without first having committed those changes, the new copy will %also contain the modifications you have made up until that point. (I %find this behaviour a little counterintuitive, which is why I mention %it here.) \hgcmd{copy}$B%3%^%s%I$r;H$&;~!$(BMercurial$B$O%o!<%-%s%0%G%#%l%/%H%jFb$N%U%!%$(B $B%k$r$=$N;~E@$N>uBV$G%3%T!<$9$k!%$9$J$o$A!$%U%!%$%k$K2?$i$+$NJQ99$r2C$(!$(B $BJQ99$N%3%_%C%H$r$;$:$K(B\hgcmd{copy}$B$r9T$&$H!$?7$?$J%3%T!<$b$=$N;~E@$^$G$K(B $B2C$($?JQ99$r4^$s$G$$$k!%(B $B!JI.<T$O$3$N5sF0$O$d$dD>4Q$KH?$9$k$H9M$($F$$$k$?(B $B$a!$4:$($F$3$3$G8@5Z$7$?!%!K(B %The \hgcmd{copy} command acts similarly to the Unix \command{cp} %command (you can use the \hgcmd{cp} alias if you prefer). The last %argument is the \emph{destination}, and all prior arguments are %\emph{sources}. If you pass it a single file as the source, and the %destination does not exist, it creates a new file with that name. %\interaction{daily.copy.simple} %If the destination is a directory, Mercurial copies its sources into %that directory. %\interaction{daily.copy.dir-dest} %Copying a directory is recursive, and preserves the directory %structure of the source. %\interaction{daily.copy.dir-src} %If the source and destination are both directories, the source tree is %recreated in the destination directory. %\interaction{daily.copy.dir-src-dest} \hgcmd{copy}$B%3%^%s%I$O(BUnix$B$N(B\command{cp}$B$HF1MM$K?6Iq$&!%!J(B\hgcmd{cp}$B%(%$(B $B%j%"%9$rDj5A$7$F;H$&$3$H$b2DG=$@!%!K0z?t$N:G8e$O(B\emph{$B%3%T!<@h(B}$B$G!$$=$l0J(B $BA0$N0z?t$O(B\emph{$B%3%T!<85(B}$B$G$"$k!%%3%T!<85$H$7$FC10l$N%U%!%$%k$r;XDj$7!$%3(B $B%T!<@h%U%!%$%k$,B8:_$7$J$$>l9g!$%3%^%s%I$O%3%T!<@h%U%!%$%k$r?75,$K:n@.$9(B $B$k!%(B \interaction{daily.copy.simple} $B%3%T!<@h$,%G%#%l%/%H%j$N>l9g!$(BMercurial$B$O%3%T!<85$r%3%T!<@h%G%#%l%/%H%j(B $B$NCf$K%3%T!<$9$k!%(B \interaction{daily.copy.dir-dest} $B%G%#%l%/%H%j$N%3%T!<$O:F5"E*$G!$%3%T!<85$N%G%#%l%/%H%j9=B$$rJ]$D!%(B \interaction{daily.copy.dir-src} $B%3%T!<85$H%3%T!<@h$,6&$K%G%#%l%/%H%j$N>l9g!$%3%T!<85$N%D%j!<9=B$$,%3%T!<(B $B@h$N%G%#%l%/%H%j$NCf$K:F8=$5$l$k!%(B \interaction{daily.copy.dir-src-dest} %As with the \hgcmd{rename} command, if you copy a file manually and %then want Mercurial to know that you've copied the file, simply use %the \hgopt{copy}{--after} option to \hgcmd{copy}. %\interaction{daily.copy.after} \hgcmd{rename}$B%3%^%s%I$HF1MM$K!$%U%!%$%k$r<jF0$G%3%T!<$7$?8e$G!$(BMercurial$B$K(B $BA`:n$rDLCN$7$?$$>l9g$O!$(B\hgcmd{copy}$B%3%^%s%I$K(B\hgopt{copy}{--after}$B%*%W(B $B%7%g%s$rIU$1$l$P$h$$!%(B \interaction{daily.copy.after} %\section{Renaming files} \section{$B%U%!%$%k$N%j%M!<%`(B} %It's rather more common to need to rename a file than to make a copy %of it. The reason I discussed the \hgcmd{copy} command before talking %about renaming files is that Mercurial treats a rename in essentially %the same way as a copy. Therefore, knowing what Mercurial does when %you copy a file tells you what to expect when you rename a file. $B%U%!%$%k$r%j%M!<%`$9$k$3$H$O%U%!%$%k$N%3%T!<$h$j$b$h$/9T$o$l$k!%%U%!%$%k(B $B$N%j%M!<%`$h$j$bA0$K(B\hgcmd{copy}$B$K$D$$$F=R$Y$?M}M3$O!$(B Mercurial$B$,K\<AE*(B $B$K%j%M!<%`$r%3%T!<$HF1MM$K07$&$+$i$G$"$k!%=>$C$F!$%U%!%$%k$r%3%T!<$9$k;~(B $B$K(BMercurial$B$,9T$&$3$H$rCN$k$3$H$O!$%j%M!<%`$N:]$K5/$3$k$3$H$rCN$k$3$H$K$J(B $B$k!%(B %When you use the \hgcmd{rename} command, Mercurial makes a copy of %each source file, then deletes it and marks the file as removed. %\interaction{daily.rename.rename} %The \hgcmd{status} command shows the newly copied file as added, and %the copied-from file as removed. %\interaction{daily.rename.status} \hgcmd{rename}$B%3%^%s%I$r;H$&;~!$(BMercurial$B$O3F!9$N%=!<%9%U%!%$%k$r%3%T!<(B $B$7!$85$N%U%!%$%k$r:o=|$7$F!$>C5n:Q$_$H%^!<%/$9$k!%(B \interaction{daily.rename.rename} \hgcmd{status}$B%3%^%s%I$O?7$?$K%3%T!<$5$l$?%U%!%$%k$rDI2C$5$l$?%U%!%$%k$H(B $B$7$FI=<($7!$%3%T!<$5$l$?%U%!%$%k$r>C5n$5$l$?%U%!%$%k$HI=<($9$k!%(B \interaction{daily.rename.status} %As with the results of a \hgcmd{copy}, we must use the %\hgopt{status}{-C} option to \hgcmd{status} to see that the added file %is really being tracked by Mercurial as a copy of the original, now %removed, file. %\interaction{daily.rename.status-copy} \hgcmd{copy}$B%3%^%s%I$N>l9g$HF1MM$K!$(B \hgcmd{status}$B%3%^%s%I$K(B \hgopt{status}{-C}$B%*%W%7%g%s$rMQ$$$F!$DI2C$5$l$?%U%!%$%k$,>C5n$5$l$?%*%j(B $B%8%J%k%U%!%$%k$N%3%T!<$H$7$F(BMercurial$B$KDI@W$5$l$F$$$k$N$+$rD4$Y$k$3$H$,$G(B $B$-$k!%(B \interaction{daily.rename.status-copy} %As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about %a rename after the fact using the \hgopt{rename}{--after} option. In %most other respects, the behaviour of the \hgcmd{rename} command, and %the options it accepts, are similar to the \hgcmd{copy} command. \hgcmd{remove}$B$H(B\hgcmd{copy}$B$N$h$&$K!$(B\hgopt{rename}{--after}$B%*%W%7%g%s$r(B $B;H$&$3$H$G!$;v8e$K%j%M!<%`$r$9$k$3$H$,$G$-$k!%B?$/$NE@$G(B\hgcmd{rename}$B%3(B $B%^%s%I$N5sF0$H!$$3$N%3%^%s%I$,<u$1F~$l$k%*%W%7%g%s$O(B\hgcmd{copy}$B%3%^%s%I(B $B$HN`;w$7$F$$$k!%(B %\subsection{Renaming files and merging changes} \subsection{$B%U%!%$%k$N%j%M!<%`$HJQ99$N%^!<%8(B} %Since Mercurial's rename is implemented as copy-and-remove, the same %propagation of changes happens when you merge after a rename as after %a copy. Mercurial$B$N%j%M!<%`$O%3%T!<$H:o=|$H$7$F<BAu$5$l$F$*$j!$%j%M!<%`8e$K%^!<(B $B%8$r9T$&$N$H!$%3%T!<8e$K%^!<%8$r9T$&$N$G$OF1$8JQ99$NGH5Z$,5/$-$k!%(B %If I modify a file, and you rename it to a new name, and then we merge %our respective changes, my modifications to the file under its %original name will be propagated into the file under its new name. %(This is something you might expect to ``simply work,'' but not all %revision control systems actually do this.) $B;d$,%U%!%$%k$rJQ99$7!$$"$J$?$,$=$N%U%!%$%k$r$r?7$7$$L>A0$K%j%M!<%`$7$?>l(B $B9g!$2f!9$,$*8_$$$NJQ99$r%^!<%8$9$k$H85$N%U%!%$%kL>$KBP$9$k;d$NJQ99$O!$?7(B $B$7$$%U%!%$%kL>$N%U%!%$%k$KGH5Z$9$k!%(B $B!J$3$l$,$G$-$k$N$OEv$?$jA0$H;W$&$+$b(B $B$7$l$J$$$,!$<B$N$H$3$m!$A4$F$N%j%S%8%g%s%3%s%H%m!<%k%7%9%F%`$,$G$-$k$o$1(B $B$G$O$J$$!%!K(B %Whereas having changes follow a copy is a feature where you can %perhaps nod and say ``yes, that might be useful,'' it should be clear %that having them follow a rename is definitely important. Without %this facility, it would simply be too easy for changes to become %orphaned when files are renamed. $BJQ99$,%3%T!<$K=>$&5!G=$,M-MQ$G$"$k$3$H$O!$$*$=$i$/MF0W$KF10U$,F@$i$l$k$H(B $B$3$m$G$"$k$H;W$o$l$k!%$H$j$o$1%j%M!<%`$KDI=>$9$k5!G=$O$-$o$a$F=EMW$G$"$k(B $B$3$H$OL@Gr$G$"$k!%$b$7$3$N5!G=$,$J$1$l$P!$%U%!%$%k$N%j%M!<%`$K$h$C$FJQ99(B $B$OMF0W$/9T$->l$r<:$C$F$7$^$&$@$m$&!%(B %\subsection{Divergent renames and merging} \subsection{$BL>A0$H%^!<%8$NH/;6(B} %The case of diverging names occurs when two developers start with a %file---let's call it \filename{foo}---in their respective %repositories. 2$B?M$N3+H/<T$N%j%]%8%H%j4V$G(B1$B$D$N%U%!%$%k(B ---\filename{foo}$B$H8F$V$3$H$K$9(B $B$k(B--- $B$K$D$$$FL>A0$NH/;6$,5/$3$C$?>l9g$K$D$$$F9M$($F$_$h$&!%(B \interaction{rename.divergent.clone} %Anne renames the file to \filename{bar}. $B%"%s$O%U%!%$%k$r(B\filename{bar}$B$H2~L>$7$?!%(B \interaction{rename.divergent.rename.anne} %Meanwhile, Bob renames it to \filename{quux}. $B$=$N4V!$%\%V$OF1$8%U%!%$%k$r(B\filename{quux}$B$H2~L>$7$?!%(B \interaction{rename.divergent.rename.bob} %I like to think of this as a conflict because each developer has %expressed different intentions about what the file ought to be named. $B3F!9$N3+H/<T$O%U%!%$%k$,$I$N$h$&$K8F$P$l$k$Y$-$+$K$D$$$F0[$J$C$?0U?^$r;}$C(B $B$F$*$j!$$3$l$O%3%s%U%j%/%H$H9M$($i$l$k!%(B %What do you think should happen when they merge their work? %Mercurial's actual behaviour is that it always preserves \emph{both} %names when it merges changesets that contain divergent renames. %\interaction{rename.divergent.merge} $BH`$i$,%^!<%8$r9T$C$?:]$K$I$&$J$l$P$h$$$@$m$&$+!)(B Mercurial$B$N<B:]$N5sF0(B $B$O!$H/;6$7$?%j%M!<%`$,$"$k%A%'%s%8%;%C%H$r%^!<%8$7$?>l9g$O>o$K(B\emph{$BN>J}(B}$B$N(B $BL>A0$rJ]B8$9$k!%(B \interaction{rename.divergent.merge} %Notice that Mercurial does warn about the divergent renames, but it %leaves it up to you to do something about the divergence after the merge. Mercurial$B$OL>A0$NH/;6$K$D$$$F7Y9p$9$k$,!$%^!<%88e$bL>A0$NH/;6$N2r7h$O%f!<(B $B%6$KG$$;$kE@$KCm0U!%(B %\subsection{Convergent renames and merging} \subsection{$B%j%M!<%`$H%^!<%8$K$h$k<}B+(B} %Another kind of rename conflict occurs when two people choose to %rename different \emph{source} files to the same \emph{destination}. %In this case, Mercurial runs its normal merge machinery, and lets you %guide it to a suitable resolution. 2$B?M$N%f!<%6$,0[$J$k(B\emph{$B%=!<%9(B}$B%U%!%$%k72$rF10l$N(B\emph{$BL\E*(B}$B%U%!%$%k$K%j(B $B%M!<%`$9$k$H>WFM$,5/$-$k!%$3$N>l9g!$(BMercurial$B$ODL>o$N%^!<%85!9=$r5/F0$7!$(B $B%f!<%6$KE,@Z$J2r7h$rB%$9!%(B %\subsection{Other name-related corner cases} \subsection{$BL>A0$K4XO"$7$?$$$/$D$+$NLdBj(B} %Mercurial has a longstanding bug in which it fails to handle a merge %where one side has a file with a given name, while another has a %directory with the same name. This is documented as~\bug{29} . %\interaction{issue29.go} Mercurial$B$K$O!$0lJ}$rL>A0$rM?$($?%U%!%$%k!$$b$&0lJ}$rF1L>$N%G%#%l%/%H%j$H(B $B$7$F%^!<%8$r9T$&$H<:GT$9$k%P%0$,0JA0$+$i$"$k!%$3$l$O(B~\bug{29}$B$H$7$F%I%-%e(B $B%a%s%H2=$5$l$F$$$k!%(B \interaction{issue29.go} %\section{Recovering from mistakes} \section{$B%_%9$+$i$N2sI|(B} %Mercurial has some useful commands that will help you to recover from %some common mistakes. Mercurial$B$K$O0lHLE*$J%_%9$+$i$N2sI|$r=u$1$k$$$/$D$+$NM-MQ$J%3%^%s%I$,$"$k!%(B %The \hgcmd{revert} command lets you undo changes that you have made to %your working directory. For example, if you \hgcmd{add} a file by %accident, just run \hgcmd{revert} with the name of the file you added, %and while the file won't be touched in any way, it won't be tracked %for adding by Mercurial any longer, either. You can also use %\hgcmd{revert} to get rid of erroneous changes to a file. \hgcmd{revert}$B%3%^%s%I$O%o!<%-%s%0%G%#%l%/%H%jFb$G9T$C$?JQ99$r<h$j>C$9!%(B $B$?$H$($P!$8m$C$F(B\hgcmd{add}$B$r9T$C$?>l9g!$DI2C$7$?%U%!%$%kL>$H6&$K(B \hgcmd{revert}$B$r<B9T$9$l$P%U%!%$%k$O2?$bJQ99$5$l$:!$(BMercurial$B$N4IM}$+$i30(B $B$5$l$k!%$^$?(B\hgcmd{revert}$B$O%U%!%$%k$X$N4V0c$C$?JQ99$r>C5n$9$k$N$b;H$($k!%(B %It's useful to remember that the \hgcmd{revert} command is useful for %changes that you have not yet committed. Once you've committed a %change, if you decide it was a mistake, you can still do something %about it, though your options may be more limited. \hgcmd{revert}$B%3%^%s%I$OL$%3%_%C%H$NJQ99$KBP$7$FM-8z$G$"$k$3$H$r3P$($F$*(B $B$/$HNI$$!%JQ99$r%3%_%C%H$7$?$"$H$G!$$3$l$,4V0c$$$G$"$C$?$3$H$K5$$E$$$?>l(B $B9g$O!$$H$l$k<jCJ$O$d$d8B$i$l$k!%(B %For more information about the \hgcmd{revert} command, and details %about how to deal with changes you have already committed, see %chapter~\ref{chap:undo}. \hgcmd{revert}$B%3%^%s%I$K$D$$$F$N$h$j>\:Y$J>pJs$H!$$9$G$K%3%_%C%H$7$?JQ99(B $B$X$NA`:n$K$D$$$F$O(B~\ref{chap:undo}$B$N>O$r;2>H$5$l$?$$!%(B %%% Local Variables: %%% mode: yatex %%% TeX-master: "00book" %%% End: