
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
bos@117: makes in such cases is that we 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@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@118: If I modify a file, and you rename it to a new name, then we merge our
bos@118: respective changes, my modifications to the file under its original
bos@118: name will be propagated into the file under its new name.  (This is
bos@118: something you might expect to ``simply work,'' but not all revision
bos@118: control systems actually do this.)
bos@43: 
bos@42: %%% Local Variables: 
bos@42: %%% mode: latex
bos@42: %%% TeX-master: "00book"
bos@42: %%% End: 




