Mercurial_ The Definitive Guide - Bryan O'Sullivan [32]
What’s going on is that in the former case, we explicitly named the file to add on the command line. The assumption that Mercurial makes in such cases is that we know what we are doing, and it doesn’t print any output.
However, when we 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 behavior is common to most Mercurial commands.
Mercurial Tracks Files, Not Directories
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.
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.
If you need an empty directory in your repository, there are a few ways to achieve this. One is to create a directory, then hg add a “hidden” file to that directory. On Unix-like systems, any filename that begins with a period (.) is treated as hidden by most commands and GUI tools. This approach is illustrated below.
$ hg init hidden-example
$ cd hidden-example
$ mkdir empty
$ touch empty/.hidden
$ hg add empty/.hidden
$ hg commit -m 'Manage an empty-looking directory'
$ ls empty
$ cd ..
$ hg clone hidden-example tmp
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ ls tmp
empty
$ ls tmp/empty
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.
How to Stop Tracking a File
Once you decide that a file no longer belongs in your repository, use the hg remove command. This deletes the file, and tells Mercurial to stop tracking it (which will occur at the next commit). A removed file is represented in the output of hg status with an R.
$ hg init remove-example
$ cd remove-example
$ echo a > a
$ mkdir b
$ echo b > b/b
$ hg add a b
adding b/b
$ hg commit -m 'Small example for file removal'
$ hg remove a
$ hg status
R a
$ hg remove b
removing b/b
After you hg 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 hg add it. Mercurial will know that the newly added file is not related to the old file of the same name.
Removing a File Does Not Affect Its History
It is important to understand that removing a file has only two effects:
It removes the current version of the file from the working directory.
It stops Mercurial from tracking changes to the file, from the time of the next commit.
Removing a file does not in any way alter the history of the file.
If you update the working directory to a changeset that was committed when it was still tracking a file that you later removed, the file 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.
Missing Files
Mercurial considers a file that you have deleted, but not used hg remove to delete, to be missing. A missing file is represented with !