This is a guest blog post by Steve Losh focusing on the primary reasons a team may choose Mercurial as their (distributed) version control system. Check out Steve’s projects to see some of the cool things he has worked on around Distributed Version Control, or jump over to his Bitbucket account and fork one of his many projects.
In our previous posts, we talked about the history of version control and why it’s a good thing, as well as why distributed version control systems are better than centralized systems.
There are two major distributed version control systems in widespread use today: Mercurial (Hg) and Git. There are many reasons (and opinions) why one would choose Git or Hg, and the next two blog posts in this series aim to explain some of these Whys.
A Sane Command Line Interface
The command line interface is the first thing many programmers will see when using a new version control system. Mercurial’s CLI is full-featured, stable, and elegant. It follows the UNIX philosophy: “each command should do one thing and do it well.”
Git’s CLI is designed to be extremely flexible. Each command has many options that can change its behavior. This makes for less typing, but requires you to remember all of the various options and how they interact with each other. Git’s documentation must detail all the interactions between options, which makes it more verbose and difficult to skim.
Mercurial’s simple approach leads to documentation which is sleek and concise. It’s easy to find what you’re looking for — using hg help, so you can spend less time looking at docs and get back to coding. It favors clarity over “cleverness”, which makes for an easier-to-use tool.
Mercurial tries to be helpful by anticipating some of the more common aliases for commands and just making them work. For example, the hg rename command can also be run with hg move or hg mv. Git simply gives you a git mv command. You can create your own git move alias if you like, but that’s yet another step to try to make Git’s CLI pleasant to use while Mercurial’s is pleasant by default.
Mercurial’s CLI is also quite similar to Subversion’s, which can help ease the transition between the two tools. Here’s a comparison of some of the most common commands. Mercurial/Git commands that are the same as their Subversion equivalents are bold.
|svn add||hg add||git add|
|svn blame||hg blame||git blame|
|svn cat||hg cat||git show|
|svn checkout||hg clone||git clone|
|svn commit||hg commit ; hg push||git commit -a ; git push|
|svn delete/remove||hg remove||git rm|
|svn diff||hg diff||git diff, git diff –cached|
|svn help||hg help||git help|
|svn log||hg log||git log|
|svn revert||hg revert||git checkout -f|
|svn status||hg status||git status|
|svn update||hg pull –update||git pull|
|svn move/rename||hg move/rename||git mv|
As you can see, Git makes less of an effort to organize its CLI in a way that Subverison users will be used to. While you can work around this by retraining your fingers to type the new commands, it’s yet one more roadblock to switching systems. Worse, it simply isn’t necessary, as Mercurial’s Subversion-user-friendly but still powerful and elegant interface proves.
Safer History with Mercurial
Mercurial’s philosophy is that “history is permanent and sacred.” Core Mercurial includes only one single command that can alter history: hg rollback. This command will “undo” the last pull or commit, but will never touch anything further back.
Git, on the other hand, lets you play fast and loose with your project’s history. Commands like git rebase –interactive let you rewrite history, possibly discarding data along the way.
Yes, you can find changesets you’ve destroyed through git rebase –interactive using git reflog, but if it has been more than a month since you made the change, those changesets will be lost (Git will “garbage collect” these changesets after a month).
Including destructive commands in core means new users are more likely to shoot themselves in the foot by running commands with implications they don’t fully understand.
For the times when you do need to rewrite history in Mercurial, you can turn to extensions like collapse, histedit and MQ. Keeping this functionality out of core prevents new users from accidentally using it until they’re ready.
Most of these extensions will also permanently back up any changesets that they destroy into a bundle. These bundles will not be garbage collected, so you don’t have to worry about your version control system eating your data.
Many programmers prefer to use a graphical interface to their version control system instead of working through a command line. Several third-party GUIs have been created to make working with Mercurial easier.
One of the tools out there is SourceTree, a free Git and Mercurial Mac client offered by Atlassian. SourceTree is an easy-to-use app that connects to many of the popular source code hosting tools out there like Bitbucket, Kiln and (for Git users) GitHub.
TortoiseHg is another available tool – a shell extension for Windows, Linux and OS X that provides a mature, stable GUI to work with Mercurial. Programmers familiar with TortoiseSVN or TortoiseCVS will feel right at home working with TortoiseHg.
With Mercurial, Windows support is a first-class feature. The Mercurial crew cares about Windows users and is very concerned with being completely cross-platform. You can build core Mercurial from source on a Windows machine and use it without having to rely on prepackaged binaries if you like.
Git, on the other hand, does not provide support for Windows in its core code. There is a project called msysgit that adds compatibility for Windows. However, it is commonly reported to be slower than Git on Linux, and the fact that it is a completely separate project says something about Git’s attitude toward Windows use.
The maintainer (and original author) of Mercurial, Matt Mackall, is a strong proponent of backwards compatibility, which is important when you’re choosing a version control system that you plan to rely on for a long time.
Easy to Extend
Once you get comfortable working with Mercurial, you’ll probably find features that you wish it had. You could talk to the Mercurial developers and try to get someone to implement these features, but that can take a lot of time and effort (and they may decide they don’t want the feature at all).
Mercurial knows that everyone is going to have different needs, so it provides several ways to extend its functionality without changing the core code.
The first method of extending Mercurial is writing shell scripts that call its command line interface. The output of most Mercurial commands is in a “human-readable-but-easy-to-parse” format. It’s often quite simple to write a shell script to do what you need. For example, say you’d like to add a command to automatically paste your current diff to http://dpaste.com. You could write a tiny shell script called “hgpastediff” to do it:
hg diff | curl -si -F 'content=
Once that script is on your path you can simply run <code>hgdiffpaste</code> to paste the code to dpaste, and the location of the paste will be printed for you.
As we mentioned in the last section, Mercurial is committed to maintaining a backwards-compatible command line interface, so you'll almost never have to worry about your shell scripts breaking when you update to a new version.
Another way to extend Mercurial is to use aliases. Aliases let you define new Mercurial commands that run other commands, possibly with arguments. For example, if you work with someone named Alice and merge with her often, you may find yourself typing <em>hg commit --message "Merge with Alice."</em> often. You can define an alias in your <em>~/.hgrc</em> file to cut down on this typing:
mwa = commit -m "Merge with Alice."
The 1.7 version of Mercurial included a feature called “shell aliases” that lets you define aliases to run shell commands. We could avoid creating a separate shell script file for our “paste to dpaste” feature by using a shell alias:
diffpaste = !hg diff | curl -si -F ‘content=
Shell aliases are a quick and dirty way to make new commands that make your life easier.
Sometimes a shell script is just not powerful enough to add a feature you’d like to see in Mercurial. When that happens, you can write your own Mercurial extension using the extension API. Extensions are written in Python (like Mercurial itself), which is a very common and elegant programming language.
Writing extensions gives you full access to all of Mercurial’s internals, which means you can do just about anything you can imagine.
With a tool as important as a version control system, it’s important to be able to get support when something goes wrong. It’s also helpful to be able to pay for professional training if you don’t have any experienced users in your company already.
There are several places to turn to for Mercurial support and training. The most up-to-date list is the Support page on the Mercurial wiki.
Another place to find information about professional Mercurial consulting is the newly created mercurial-consulting mailing list. If you have specific needs, the mailing list would be the best place to ask.
Hosting Tools and Services
Programmers almost never work alone, and it’s often beneficial to have a central copy of your repositories that can be browsed easily on the web. There are several ways to make this happen.
The hg serve command fires up a web server on your local computer that other people can view in a browser and pull from. For sharing changes with another person quickly, it couldn’t be easier. For a more secure and permanent server, you’ve got a couple of choices.
Mercurial bundles a repository-serving script similar to hg serve that may fill the needs of smaller companies who just need a way to share links between people. It can run on most servers that support WSGI, and it is included with Mercurial itself.
Atlassian’s Bitbucket is a hosted service for Git and Mercurial that will host your repositories and provide many more features than the standard Mercurial web server. Plans are free for 5 users and priced for higher user tiers thereafter – with an option for unlimited private repositories available. Using Bitbucket means you don’t need to worry about buying new hard drives to host your projects or setting up new web servers for them. Bitbucket gives you an interface that “just works.”
There is also Atlassian’s FishEye which allows you to browse and search repositories in Git, Mercurial, Subversion, or any of the other supported systems — all configured within a single installation. FishEye can connect to a Bitbucket repo to give you advanced browsing and search capabilities as well. If you want a bit more out of your code review process, you can tack on the Crucible product to FishEye as well.
Bitbucket and FishEye both connect to popular issue tracking tools like JIRA or Bugzilla.
Mercurial or Git?
Now that we have given you a few reasons for Mercurial, you may want to consider using a distributed version control system. In our next blog, we’ll take a look at the advantages of using Git.
Comment and let us know if you chose Mercurial – we would love to hear why and I am sure many readers would as well. If you opted not to use Hg, we’d love to hear why not as well.