Mercurial_ The Definitive Guide - Bryan O'Sullivan [34]
First of all, remember that this propagation only happens when you merge. So if you hg copy a file, and subsequently modify the original file during the normal course of your work, nothing will happen.
The second thing to know is that modifications will only propagate across a copy as long as the changeset that you’re merging changes from hasn’t yet seen the copy.
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 hg 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.
If you pulled and merged my changes, and Mercurial didn’t propagate changes across copies, your new source file would now contain the bug, and unless you knew to propagate the bug fix by hand, the bug would remain in your copy of the file.
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 only revision control system that propagates changes across copies like this.
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 at the first merge, and not afterwards.
How to Make Changes Not Follow a Copy
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 cp) to make a copy of a file, then hg add the new copy by hand. Before you do so, though, please do reread the previous section, and make an informed decision that this behavior is not appropriate to your specific case.
Behavior of the hg copy Command
When you use the hg 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 hg 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 behavior a little counterintuitive, which is why I mention it here.)
The hg copy command acts similarly to the Unix cp command (you can use the hg cp alias if you prefer). We must supply two or more arguments, of which the last is treated as the destination, and all others are sources.
If you pass hg copy a single file as the source, and the destination does not exist, it creates a new file with that name.
$ mkdir k
$ hg copy a k
$ ls k
a
If the destination is a directory, Mercurial copies its sources into that directory.
$ mkdir d
$ hg copy a b d
$ ls d
a b
Copying a directory is recursive, and preserves the directory structure of the source.
$ hg copy z e
copying z/a/c to e/a/c
If the source and destination are both directories, the source tree is recreated in the destination directory.
$ hg copy z d
copying z/a/c to d/z/a/c
As with the hg remove command, if you copy a file manually and then want Mercurial to know that you’ve copied the file, simply use the --after option to hg copy.
$ cp a n
$ hg copy --after a n
Renaming Files
It’s rather more common to need to rename a file than to make a copy of it. The reason I discussed the hg 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.
When you use the hg rename command, Mercurial makes a copy of each source file, then deletes it and marks the file as removed.
$ hg rename a b
The hg status command shows the newly copied file as added, and the copied-from file as removed.
$ hg status
A b
R a
As with the results of a hg copy, we must use the -C option to hg status to see that the added file is