Managing your web site with Mercurial

A tutorial by Tim Post


I use the Mercurial source control system for (nearly) every one of my free software projects. Recently, I began using it to manage all of my web sites. If you are like me, you likely have a web server and SQL server of some sort running on your desktop, permitting you to work locally.

I make many frequent changes to my sites. Sometimes things don't go so well for various reasons. I may need to roll back changes that I made to something, get my site mirrored in a hurry if its getting an abnormal amount of visits, change hosts in a hurry, lots of other things. Mercurial helps with everything.

Now I can work locally and just 'hg push' my changes to my server, make changes on the server and easily 'hg pull' them to my local copy, or merge if I've modified the same files in both places. I can quickly grab a whole copy of my web site to setup a mirror on many other systems, or even quickly produce patches to send upstream to free software projects (like Wordpress, phpbb, etc).

All of this is done easily, effortlessly and securely via SSH. No more FTP'ing for me! Here's how I do it, you might like this method (or something similar).

Questions or comments regarding this tutorial can be sent to tinkertim@gmail.com, please allow a few days for a response.

Tutorial Objectives

Materials Needed

Step #1 - Generate and install SSH key pairs

You'll need SSH access to the computer that hosts your web site, for convenience, we're going to set up a key-pair permitting you@yourcomputer to access yourusername@yourwebhost without using a password. This allows Mercurial to 'just do it' when you issue a command. On a GNU/Linux system, you would do this as such:

ssh-keygen -t dsa -f ~/.ssh/my_key.dsa
(enter a passphrase if you wish, just hit [enter] when asked if you want password-less operation)

Now, install your public key on your host's computer:

scp ~/.ssh/my_key.dsa myusername@mydomain.com:~/.ssh/my_dsa_key.pub (enter your password)
ssh myusername@mydomain.com (enter your password)
cd .ssh
cat my_dsa_key.pub >> authorized_keys2
chmod 0640 authorized_keys2 (!! IMPORTANT !!)
rm -f my_dsa_key.pub
exit

You should now be able to ssh yourusername@yourdomain.tld without entering a password.

Step #2 - Install and (briefly) configure Mercurial

I'm not going to go into how to install Mercurial since there are so many ways that it can be installed. Depending on your OS, you might be able to 'yum' or 'apt-get' install mercurial. If not, try visiting the Mercurial web site and find one of the many tutorials that fits your OS. Personally, I install it from source and keep up with the latest release version. Once Mercurial is installed, you'll want to create a file named .hgrc in your home directory, this tells Mercurial some info about you as well as your preferences in editors. My /home/me/.hgrc looks like this:

tpost@tower:~/desktop/echoreply.hg $ cat ~/.hgrc
[ui]
username = Tim Post
editor = nano

You could specify whatever you want for editor, I like nano (AKA pico), however you might want emacs or VI. This will be the editor Mercurial launches when its time to review commitments or sift through merges, be sure to pick something easy to use that doesn't auto-wrap or other annoying things.

Step #3 - Initalize HG on your hosting account

Ther is absolutely no reason for your web host to not install Mercurial. It is completely safe, solid, used by many software projects and extremely easy to install. Once you are sure that you have Mercurial available on your server, go to your web root (usually /home/myusername/public_html/) and type:

hg init

Now, we need to teach Mercurial to ignore certain files and secure it a bit before we begin using it. In your public_html directory, you need to create a file named .hgignore that looks something like this:

syntax: glob
*~
*.db
*.old
*.bak
*.tmp
.htaccess
hg/
cgi-bin/
tgz-snaps/
logs/
tech/wp-config.php

Notice, I have Mercurial ignoring my wordpress configuration file. This is for two reasons, one being security, the other so that it does not over-write my local configuration file. Everything else is pretty obvious, temporary files, editor backup files, etc should not become part of the mix.

Now, create a .hgrc file identical to the one that you created earlier, this time on the remote server, this enables you to commit changes in both places.

After typing 'hg init', a directory named .hg was created. You want to keep people out of there, unless of course there's no need to keep any files in your web root private. Do this by adding a simple .htaccess file in .hg/ that looks like this:

<Limit GET POST>
order allow,deny
deny from all
</Limit>

Accessing http://yourdomain.com/.hg/ should give you a rather rude 'go away' message after doing so.

Step #4 - The first commitment

You now need to tell Mercurial (on your remote machine) to watch all of the files that you have not ignored. Do this simply by typing:

hg commit -Am "Initial checkin of my web site"

Now, you can clone your web site on your local machine by simply typing:

hg clone ssh://myusername@mydomain.tld/public_html mydomain.hg

If your domain is xyz.com, you would substitute mydomain.hg with 'xyz.hg'. I recommend doing this while in your desktop directory for ease. Next, you'll need to create any files that were ignored by .hgignore, such as your configuration files, .htaccess rules (if you ignored .htaccess) or other things. You can use the scp utility to fetch them and edit them to match your local settings, those files will not be pushed to your public server when you push changes.

Now, edit a file, save it and type:

hg commit -Am "Updated some file for some reason"
hg push
ssh myusername@mydomain.tld
hg update

If you edit files on your server and want to pull your changes to your local copy, simply type:

hg pull
hg update

Sometimes, you might need to merge. This occurs only when you have edited the same file, differently in both locations. the 'hg merge' command will take you to your editor of choice to review the changes prior to saving, once you exit the editor, Mercurial will ask if the merge was successful (based on what you just saw).

Optionally, you can tell Mercurial to do the 'hg update' remotely immediately following your push, however I don't like to do this because I frequently need to merge. Type 'hg --help push' to get more info on how to do this automatically.

Congradulations :) You can now easily push and pull changes to and from your site with the ability to quickly revert your changes (check out hg --help revert or hg --help rollback) to learn more.

Benefits of using Mercurial for site management

If you have any problems following this tutorial, feel free to drop in, I'm tinkertim@gmail.com. This has made life much easier for me when it comes to maintaining my sites, hopefully this tutorial is of some use to you :)

Copyright © 2007-2010 Tim Post - All Rights Reserved

Verbatim copies of this document in any medium are permitted provided that you leave the above copyright notice in tact.