Saturday, December 12, 2009

Mercurial Relink Extension and hg-relink.py

In newer versions of Mercurial (greater than 1.3.1), a great extension called relink comes bundled with the system. For larger projects, this can significantly reduce the amount of disk space consumed when you have a large number of cloned repositories.

When a repository is locally cloned, Mercurial will create hardlinks to the original repository's files in order to save space, if the operating system and file system support hardlinking. However, when a pull is done into either repository (the original or the cloned), those hardlinks are broken, regardless of whether the files are still identical. The relink extension allows Mercurial to re-create those hardlinks. For those of you stuck with 1.3.1 or a prior version, see the last section of this post for the solution used before this extension.

Since the relink extension is bundled with Mercurial, to activate it, just add the standard lines to your .hgrc.

[extensions]
.
.
.
relink =


Using the extension is very straightforward. Execute one of the following commands from somewhere within the cloned repository's directory structure.

# Re-link with the stored origin (the original repository this was cloned from.)
hg relink

# Relink with a specific ORIGIN repository.
hg relink /path/to/origin


Mercurial will print out which repositories were relinked and how many files were pruned. See the official extension page, or type hg help relink in a terminal for more information on usage and output.

For users of version 1.3.1 and prior:
There is a python script (contrib/hg-relink.py, or sometimes contrib/relink.py) in the source tree that provides this same functionality, and can be used with versions 1.3.1 and prior. I used it myself until I found out about the relink extension.

The usage is just as easy as the extension, but requires some extra setup. First, copy the hg-relink.py (or relink.py) file to a directory in your PATH. You can then call it as shown below:

python hg-relink.py /path/to/source /path/to/destination


The script will then hardlink the appropriate files from the source repository to the destination repository. There used to be a page on the Mercurial wiki describing this script in more detail, but it seems to have disappeared.