bos@42: \chapter{Mercurial in daily use} bos@42: \label{chap:daily} bos@42: bos@117: \section{Telling Mercurial which files to track} bos@42: bos@42: Mercurial does not work with files in your repository unless you tell bos@42: it to manage them. The \hgcmd{status} command will tell you which bos@42: files Mercurial doesn't know about; it uses a ``\texttt{?}'' to bos@42: display such files. bos@42: bos@42: To tell Mercurial to track a file, use the \hgcmd{add} command. Once bos@42: you have added a file, the entry in the output of \hgcmd{status} for bos@42: that file changes from ``\texttt{?}'' to ``\texttt{A}''. bos@117: \interaction{daily.files.add} bos@42: bos@42: After you run a \hgcmd{commit}, the files that you added before the bos@42: commit will no longer be listed in the output of \hgcmd{status}. The bos@42: reason for this is that \hgcmd{status} only tells you about bos@117: ``interesting'' files---those that you have modified or told Mercurial bos@117: to do something with---by default. If you have a repository that bos@42: contains thousands of files, you will rarely want to know about files bos@42: that Mercurial is tracking, but that have not changed. (You can still bos@42: get this information; we'll return to this later.) bos@42: bos@117: Once you add a file, Mercurial doesn't do anything with it bos@117: immediately. Instead, it will take a snapshot of the file's state the bos@117: next time you perform a commit. It will then continue to track the bos@117: changes you make to the file every time you commit, until you remove bos@117: the file. bos@117: bos@117: \subsection{Explicit versus implicit file naming} bos@117: bos@117: A useful behaviour that Mercurial has is that if you pass the name of bos@117: a directory to a command, every Mercurial command will treat this as bos@117: ``I want to operate on every file in this directory and its bos@117: subdirectories''. bos@117: \interaction{daily.files.add-dir} bos@117: Notice in this example that Mercurial printed the names of the files bos@117: it added, whereas it didn't do so when we added the file named bos@117: \filename{a} in the earlier example. bos@117: bos@117: What's going on is that in the former case, we explicitly named the bos@117: file to add on the command line, so the assumption that Mercurial steve@178: makes in such cases is that you know what you were doing, and it bos@117: doesn't print any output. bos@117: bos@117: However, when we \emph{imply} the names of files by giving the name of bos@117: a directory, Mercurial takes the extra step of printing the name of bos@117: each file that it does something with. This makes it more clear what bos@117: is happening, and reduces the likelihood of a silent and nasty bos@117: surprise. This behaviour is common to most Mercurial commands. bos@117: bos@117: \subsection{Aside: Mercurial tracks files, not directories} bos@42: bos@42: Mercurial does not track directory information. Instead, it tracks bos@117: the path to a file. Before creating a file, it first creates any bos@117: missing directory components of the path. After it deletes a file, it bos@117: then deletes any empty directories that were in the deleted file's bos@117: path. This sounds like a trivial distinction, but it has one minor bos@42: practical consequence: it is not possible to represent a completely bos@42: empty directory in Mercurial. bos@42: bos@42: Empty directories are rarely useful, and there are unintrusive bos@42: workarounds that you can use to achieve an appropriate effect. The bos@42: developers of Mercurial thus felt that the complexity that would be bos@42: required to manage empty directories was not worth the limited benefit bos@42: this feature would bring. bos@42: bos@42: If you need an empty directory in your repository, there are a few bos@42: ways to achieve this. One is to create a directory, then \hgcmd{add} a bos@42: ``hidden'' file to that directory. On Unix-like systems, any file bos@42: name that begins with a period (``\texttt{.}'') is treated as hidden bos@42: by most commands and GUI tools. This approach is illustrated in bos@43: figure~\ref{ex:daily:hidden}. bos@42: bos@42: \begin{figure}[ht] bos@43: \interaction{daily.files.hidden} bos@43: \caption{Simulating an empty directory using a hidden file} bos@43: \label{ex:daily:hidden} bos@42: \end{figure} bos@42: bos@42: Another way to tackle a need for an empty directory is to simply bos@42: create one in your automated build scripts before they will need it. bos@42: bos@117: \section{How to stop tracking a file} bos@117: bos@117: Once you decide that a file no longer belongs in your repository, use bos@42: the \hgcmd{remove} command; this deletes the file, and tells Mercurial bos@43: to stop tracking it. A removed file is represented in the output of bos@43: \hgcmd{status} with a ``\texttt{R}''. bos@117: \interaction{daily.files.remove} bos@117: bos@118: After you \hgcmd{remove} a file, Mercurial will no longer track bos@118: changes to that file, even if you recreate a file with the same name bos@118: in your working directory. If you do recreate a file with the same bos@118: name and want Mercurial to track the new file, simply \hgcmd{add} it. bos@118: Mercurial will know that the newly added file is not related to the bos@118: old file of the same name. bos@118: bos@118: \subsection{Removing a file does not affect its history} bos@118: bos@118: It is important to understand that removing a file has only two bos@118: effects. bos@118: \begin{itemize} bos@118: \item It removes the current version of the file from the working bos@118: directory. bos@118: \item It stops Mercurial from tracking changes to the file, from the bos@118: time of the next commit. bos@118: \end{itemize} bos@118: Removing a file \emph{does not} in any way alter the \emph{history} of bos@118: the file. bos@118: bos@118: If you update the working directory to a changeset in which a file bos@118: that you have removed was still tracked, it will reappear in the bos@118: working directory, with the contents it had when you committed that bos@118: changeset. If you then update the working directory to a later bos@118: changeset, in which the file had been removed, Mercurial will once bos@118: again remove the file from the working directory. bos@118: bos@117: \subsection{Missing files} bos@42: bos@43: Mercurial considers a file that you have deleted, but not used bos@43: \hgcmd{remove} to delete, to be \emph{missing}. A missing file is bos@43: represented with ``\texttt{!}'' in the output of \hgcmd{status}. bos@117: Mercurial commands will not generally do anything with missing files. bos@117: \interaction{daily.files.missing} bos@117: bos@117: If your repository contains a file that \hgcmd{status} reports as bos@117: missing, and you want the file to stay gone, you can run bos@117: \hgcmdargs{remove}{\hgopt{remove}{--after}} at any time later on, to bos@117: tell Mercurial that you really did mean to remove the file. bos@117: \interaction{daily.files.remove-after} bos@117: bos@117: On the other hand, if you deleted the missing file by accident, use bos@117: \hgcmdargs{revert}{\emph{filename}} to recover the file. It will bos@117: reappear, in unmodified form. bos@117: \interaction{daily.files.recover-missing} bos@117: bos@117: \subsection{Aside: why tell Mercurial explicitly to bos@117: remove a file?} bos@117: bos@117: You might wonder why Mercurial requires you to explicitly tell it that bos@117: you are deleting a file. Early during the development of Mercurial, bos@117: it let you delete a file however you pleased; Mercurial would notice bos@117: the absence of the file automatically when you next ran a bos@117: \hgcmd{commit}, and stop tracking the file. In practice, this made it bos@117: too easy to accidentally remove a file without noticing. bos@117: bos@117: \subsection{Useful shorthand---adding and removing files bos@117: in one step} bos@42: bos@43: Mercurial offers a combination command, \hgcmd{addremove}, that adds bos@117: untracked files and marks missing files as removed. bos@117: \interaction{daily.files.addremove} bos@117: The \hgcmd{commit} command also provides a \hgopt{commit}{-A} option bos@117: that performs this same add-and-remove, immediately followed by a bos@117: commit. bos@117: \interaction{daily.files.commit-addremove} bos@117: bos@117: \section{Copying files} bos@117: bos@117: Mercurial provides a \hgcmd{copy} command that lets you make a new bos@117: copy of a file. When you copy a file using this command, Mercurial bos@117: makes a record of the fact that the new file is a copy of the original bos@117: file. It treats these copied files specially when you merge your work bos@117: with someone else's. bos@117: bos@121: \subsection{The results of copying during a merge} bos@121: bos@117: What happens during a merge is that changes ``follow'' a copy. To bos@117: best illustrate what this means, let's create an example. We'll start bos@117: with the usual tiny repository that contains a single file. bos@117: \interaction{daily.copy.init} bos@117: We need to do some work in parallel, so that we'll have something to bos@117: merge. So let's clone our repository. bos@117: \interaction{daily.copy.clone} bos@117: Back in our initial repository, let's use the \hgcmd{copy} command to bos@117: make a copy of the first file we created. bos@117: \interaction{daily.copy.copy} bos@117: bos@117: If we look at the output of the \hgcmd{status} command afterwards, the bos@117: copied file looks just like a normal added file. bos@117: \interaction{daily.copy.status} bos@117: But if we pass the \hgopt{status}{-C} option to \hgcmd{status}, it bos@117: prints another line of output: this is the file that our newly-added bos@117: file was copied \emph{from}. bos@117: \interaction{daily.copy.status-copy} bos@117: bos@117: Now, back in the repository we cloned, let's make a change in bos@117: parallel. We'll add a line of content to the original file that we bos@117: created. bos@117: \interaction{daily.copy.other} bos@117: Now we have a modified \filename{file} in this repository. When we bos@117: pull the changes from the first repository, and merge the two heads, bos@117: Mercurial will propagate the changes that we made locally to bos@117: \filename{file} into its copy, \filename{new-file}. bos@117: \interaction{daily.copy.merge} bos@117: bos@117: \subsection{Why should changes follow copies?} bos@117: \label{sec:daily:why-copy} bos@117: bos@117: This behaviour, of changes to a file propagating out to copies of the bos@117: file, might seem esoteric, but in most cases it's highly desirable. bos@117: bos@117: First of all, remember that this propagation \emph{only} happens when bos@117: you merge. So if you \hgcmd{copy} a file, and subsequently modify the bos@117: original file during the normal course of your work, nothing will bos@117: happen. bos@117: bos@117: The second thing to know is that modifications will only propagate bos@117: across a copy as long as the repository that you're pulling changes bos@117: from \emph{doesn't know} about the copy. bos@117: bos@117: The reason that Mercurial does this is as follows. Let's say I make bos@117: an important bug fix in a source file, and commit my changes. bos@117: Meanwhile, you've decided to \hgcmd{copy} the file in your repository, bos@117: without knowing about the bug or having seen the fix, and you have bos@117: started hacking on your copy of the file. bos@117: bos@117: If you pulled and merged my changes, and Mercurial \emph{didn't} bos@117: propagate changes across copies, your source file would now contain bos@117: the bug, and unless you remembered to propagate the bug fix by hand, bos@117: the bug would \emph{remain} in your copy of the file. bos@117: bos@117: By automatically propagating the change that fixed the bug from the bos@117: original file to the copy, Mercurial prevents this class of problem. bos@117: To my knowledge, Mercurial is the \emph{only} revision control system bos@117: that propagates changes across copies like this. bos@117: bos@117: Once your change history has a record that the copy and subsequent bos@117: merge occurred, there's usually no further need to propagate changes bos@117: from the original file to the copied file, and that's why Mercurial bos@117: only propagates changes across copies until this point, and no bos@117: further. bos@117: bos@117: \subsection{How to make changes \emph{not} follow a copy} bos@117: bos@117: If, for some reason, you decide that this business of automatically bos@117: propagating changes across copies is not for you, simply use your bos@117: system's normal file copy command (on Unix-like systems, that's bos@117: \command{cp}) to make a copy of a file, then \hgcmd{add} the new copy bos@117: by hand. Before you do so, though, please do reread bos@117: section~\ref{sec:daily:why-copy}, and make an informed decision that bos@117: this behaviour is not appropriate to your specific case. bos@117: bos@117: \subsection{Behaviour of the \hgcmd{copy} command} bos@117: bos@118: When you use the \hgcmd{copy} command, Mercurial makes a copy of each bos@118: source file as it currently stands in the working directory. This bos@118: means that if you make some modifications to a file, then copy it bos@118: without first having committed those changes, the new copy will bos@118: contain your modifications. bos@118: bos@117: The \hgcmd{copy} command acts similarly to the Unix \command{cp} bos@118: command (you can use the \hgcmd{cp} alias if you prefer). The last bos@118: argument is the \emph{destination}, and all prior arguments are bos@118: \emph{sources}. If you pass it a single file as the source, and the bos@118: destination does not exist, it creates a new file with that name. bos@117: \interaction{daily.copy.simple} bos@117: If the destination is a directory, Mercurial copies its sources into bos@117: that directory. bos@117: \interaction{daily.copy.dir-dest} bos@117: Copying a directory is recursive, and preserves the directory bos@117: structure of the source. bos@117: \interaction{daily.copy.dir-src} bos@117: If the source and destination are both directories, the source tree is bos@117: recreated in the destination directory. bos@117: \interaction{daily.copy.dir-src-dest} bos@117: bos@118: As with the \hgcmd{rename} command, if you copy a file manually and bos@118: then want Mercurial to know that you've copied the file, simply use bos@118: the \hgopt{--after} option to \hgcmd{copy}. bos@118: \interaction{daily.copy.after} bos@118: bos@117: \section{Renaming files} bos@43: bos@118: It's rather more common to need to rename a file than to make a copy bos@118: of it. The reason I discussed the \hgcmd{copy} command before talking bos@118: about renaming files is that Mercurial treats a rename in essentially bos@118: the same way as a copy. Therefore, knowing what Mercurial does when bos@118: you copy a file tells you what to expect when you rename a file. bos@118: bos@118: When you use the \hgcmd{rename} command, Mercurial makes a copy of bos@118: each source file, then deletes it and marks the file as removed. bos@118: \interaction{daily.rename.rename} bos@118: The \hgcmd{status} command shows the newly copied file as added, and bos@118: the copied-from file as removed. bos@118: \interaction{daily.rename.status} bos@118: As with the results of a \hgcmd{copy}, we must use the bos@118: \hgopt{status}{-C} option to \hgcmd{status} to see that the added file bos@118: is really being tracked by Mercurial as a copy of the original, now bos@118: removed, file. bos@118: \interaction{daily.rename.status-copy} bos@118: bos@118: As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about bos@118: a rename after the fact using the \hgopt{rename}{--after} option. In bos@118: most other respects, the behaviour of the \hgcmd{rename} command, and bos@118: the options it accepts, are similar to the \hgcmd{copy} command. bos@118: bos@118: \subsection{Renaming files and merging changes} bos@118: bos@118: Since Mercurial's rename is implemented as copy-and-remove, the same bos@118: propagation of changes happens when you merge after a rename as after bos@118: a copy. bos@118: bos@156: If I modify a file, and you rename it to a new name, and then we merge bos@156: our respective changes, my modifications to the file under its bos@156: original name will be propagated into the file under its new name. bos@156: (This is something you might expect to ``simply work,'' but not all bos@156: revision control systems actually do this.) bos@43: bos@121: Whereas having changes follow a copy is a feature where you can bos@121: perhaps nod and say ``yes, that might be useful,'' it should be clear bos@121: that having them follow a rename is definitely important. Without bos@121: this facility, it would simply be too easy for changes to become bos@121: orphaned when files are renamed. bos@121: bos@156: \subsection{Divergent renames and merging} bos@156: bos@156: The case of diverging names occurs when two developers start with a bos@156: file---let's call it \filename{foo}---in their respective bos@156: repositories. bos@156: bos@156: \interaction{rename.divergent.clone} bos@156: Anne renames the file to \filename{bar}. bos@156: \interaction{rename.divergent.rename.anne} bos@156: Meanwhile, Bob renames it to \filename{quux}. bos@156: \interaction{rename.divergent.rename.bob} bos@156: bos@156: I like to think of this as a conflict because each developer has bos@156: expressed different intentions about what the file ought to be named. bos@156: bos@156: What do you think should happen when they merge their work? bos@156: Mercurial's actual behaviour is that it always preserves \emph{both} bos@156: names when it merges changesets that contain divergent renames. bos@156: \interaction{rename.divergent.merge} bos@156: bos@156: I personally find this behaviour quite surprising, which is why I bos@156: wanted to explicitly mention it here. I would have expected Mercurial bos@156: to prompt me with a three-way choice instead: do I want to keep only bos@156: \filename{bar}, only \filename{quux}, or both? bos@156: bos@156: In practice, when you rename a source file, it is likely that you will bos@156: also modify another file (such as a makefile) that knows how to build bos@156: the source file. So what will happen if Anne renames a file and edits bos@156: \filename{Makefile} to build it under its new name, while Bob does the bos@156: same, but chooses a different name for the file, is that after the bos@156: merge, there will be two copies of the source file in the working bos@156: directory under different names, \emph{and} a conflict in the section bos@156: of the \filename{Makefile} that both Bob and Anne edited. bos@156: bos@156: This behaviour is considered surprising by other people, too: bos@156: see~\bug{455} for details. bos@156: bos@156: \subsection{Convergent renames and merging} bos@156: bos@156: Another kind of rename conflict occurs when two people choose to bos@156: rename different \emph{source} files to the same \emph{destination}. bos@156: In this case, Mercurial runs its normal merge machinery, and lets you bos@156: guide it to a suitable resolution. bos@156: bos@156: \subsection{Other name-related corner cases} bos@156: bos@156: Mercurial has a longstanding bug in which it fails to handle a merge bos@156: where one side has a file with a given name, while another has a bos@156: directory with the same name. This is documented as~\bug{29}. bos@156: \interaction{issue29.go} bos@121: bos@42: %%% Local Variables: bos@42: %%% mode: latex bos@42: %%% TeX-master: "00book" bos@42: %%% End: