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