Mercurial notes

Using Subversion as source control for personal files, I was finding it difficult to maintain contact with a single repository URL. Mercurial solves that problem nicely, and even plays well with Subversion.

Mercurial commands are almost identical to Subversion, when the functionality is the same.

Git solves the same problem, with more options but more complexity [ Git_notes.html ] . Mercurial is easy to use safely in a very short time.

Projects using Mercurial include Mozilla, OpenSolaris, OpenJDK, Netbeans, and Pidgin.

Mercurial is implemented in python, with some C for binary diffs. It is available on all platforms.

This example shows the most important new functionality:

http://www.selenic.com/mercurial/wiki/index.cgi/UnderstandingMercurial

Interesting tutorial here: http://hginit.com/

See the main website here: http://www.selenic.com/mercurial/wiki/

§    My install

On Ubuntu, just install with sudo apt-get install mercurial.

On CentOS, I found it necessary to get the source and install with make:
tar zxvf mercurial-1.1.2.tar.gz
cd mercurial-1.1.2
sudo make install

This installed /usr/local/bin/hg but did not put the python module in my path. Typing hg returned the error ImportError: No module named mercurial

So to my login environment I added (for two different machines):
PYTHONPATH="/usr/local/lib/python2.4/site-packages:${PYTHONPATH}"
PYTHONPATH="/usr/local/lib64/python2.4/site-packages:${PYTHONPATH}"

§    Making a Subversion working copy into an Hg respository

First check out a working copy of Subversion, and create a new Mercurial repository that shares the working copy:
svn co URL/trunk svn_hg_repo
cd svn_hg_repo
hg init
cat > .hgignore <<EOF
\.svn/
\.hgignore$
EOF
hg status
hg add
hg status
hg ci -A -m "imported from svn"
hg log

If you have a collegue who wants to share your Hg repository inside his SVN working copy, then he can do the following:
hg clone -U /path/to/svn_hg_repo_one svn_hg_repo_two
svn co URL/trunk svn_hg_repo_two
cd svn_hg_repo_two 
hg up

Alternatively, if the subversion working copy already exists:
svn co URL/trunk svn_hg_repo_two
hg clone -U /path/to/svn_hg_repo_one temp
mv temp/.hg svn_hg_repo_two/
cd svn_hg_repo_two 
hg up

Your final hg up will fail if there are inconsistencies between files in Hg and in SVN. Make sure all changes are checked into both respositories, and update again. (It is okay if some files are omitted.) After this, it is perfectly fine if the two repositories get out of synch.

The hg clone -U does require that the target directory not yet exist. The -U flag copies the Hg repository without the files, so that SVN can update those files.

Multiple developers can now merge their revisions through Hg before either checks into the centralized SVN repository.

To update this double working copy, the second user could type
cd svn_hg_repo_two 
svn up
svn st
hg pull -u /path/to/svn_hg_repo_one
hg st

The first user can use exactly the same commands, exchanging svn_hg_repo_two and svn_hg_repo_one.

§    Synchronizing with detachable media

I can make a copy of an Hg repository to a detachable disk.
cd /media/USBDISK
hg clone /path/to/svn_hg_repo hg_only

Here's a sample remote path:
hg clone ssh://host//full/path/svn_hg_repo hg_only
hg clone ssh://host/svn_hg_repo hg_only  # from home directory

Assume that copy is modified offsite.
cd /media/USBDISK/hg_only
echo foo > testfile
hg add testfile
hg ci -m test
hg log

Later that detachable disk is reconnected and you want the changes merged with the latest version of the SVN repository.

First update the original SVN working copy, and save the changes into that Hg repository.
cd $HOME/svn_hg_repo
svn up
hg ci -m "updated from SVN"

Then merge those SVN changes into the offsite Hg copy:
cd /media/USBDISK/hg_only
hg pull $HOME/svn_hg_repo
hg update

# If the update fails, then you need a merge
hg merge
hg ci -m "merged SVN updates"

Finally, pull the offsite changes into the SVN working copy and check in:
cd $HOME/svn_hg_repo
hg pull /media/USBDISK/hg_only
hg update
svn ci -m "updated from Hg"

You can also reverse the direction and push changes from one copy to another, as if you were checking into a central repository. But I find it simpler always to use pull

Bill Harlan, January, 2009


Return to parent directory.