How to Use Mercurial as Git Front-end

In this document, I am going to show you how to use mercurial as a git front-end. This is about a mercurial extension called Hg-Git, if you are already using it, or not going to use mercurial to push and pull from a git server, then this guide is not for you.

Note

If you want to learn how to use mercurial, please check out the new mercurial book, it is free online.

Why Mercurial?

I hear you, why mercurial? Why, when seemingly open source projects are migrating to git en masse? Why, when git and to some extent Github had become the de facto tool-chain for OOS development? Why, when python itself is moving away from mercurial (actually, this document is a response to this decision)? Isn't it the DVCS flame war long gone and git is the declared winner? Isn't it mercurial no longer relevant, like bzr became long ago. This is 2016, not 2006 when both git and mercurial are barely one-year-old.

To begin answering these questions, I need to state my observation first, that the git dominance is not because of mercurial is a less capable contender, it is mostly because of celebrity endorsement (git was written by Linus Torvalds and used in Linux Kernel) and Github's dominance and social lock down.

Feature-wise, there is no clear winner between git and mercurial technically, in some scenarios git works better while in some cases mercurial works better. So, there is no evidence that mercurial is superior than git, why mercurial?

I am not going to get into details about these in this document, just pointing out that mercurial has some unique features that one may find useful and cannot be found in other alternatives, such as:

  1. Specifically designed query languages revset and fileset for searching in history
  2. Built-in web server for quick one-off pulling/pushing/reviewing session
  3. Extension for large files
  4. Extension Mercurial Queues (mq), like multi-level index (in git's parlance), the mq patches can also be put under revision control
  5. Phase, a feature that provide fine-grained control about changesets' publicity, no more accidental push of secret, private changes
  6. Mercurial are easy to customize, read scaling mercurial for a real world example
  7. Some interesting ideas, like Changeset Evolution for safe sharing of history rewrites, most are experimental right now, though

Nothing is perfect, mercurial is no exception, besides the smaller market share, there is currently no plan to port the code base from python 2 to python 3 due to technical restriction. That being said, with those unique features and intuitive user interface, mercurial is a viable option even today.

I am a strong believer in "biodiversity and competition are good for a ecosystem", this is another reason that I keep using mercurial and promoting mercurial whenever possible, and the reason behind writing this document.

Okay, enough talk, so how do we use mercurial as a git client? You need an extension called Hg-Git.

Installing Hg-Git

Hg-Git can be installed as normal mercurial extension, please follow the instructions on the Hg-Git official site. Hg-Git might as well be able to be installed from your linux distribution's software repository directly.

Please make sure both extensions bookmarks and hggit are enabled afterward.

For example, with these lines in ~/.hgrc:

[extensions]
hgext.bookmarks =
hggit =

Talking to Git Server

When properly setup, you can use hg clone, hg push and hg pull against a git server as if it is serving mercurial repositories. Just remember the difference in uri schema, for example, to clone from one of my projects on github, using git:

git clone git@github.com:pyx/hymn.git

while using mercurial, the command will be:

hg clone git+ssh://git@github.com/pyx/hymn.git

Notice the difference in schema part git+ssh:// and the separator : between host and user directory became a /

You can simply hg push and hg pull from then on.

Caveat

Hg-Git keeps track of the changesets under the bookmark master, so any destructive changes, e.g hg strip or hg histedit involving master will be recorded and visible in git's history. To avoid this, deactivate bookmark master before applying any destructive changes.

For the same reason, only history up to the point of master will be pushed, and I suggest to first deactivate bookmark master while working on development branches, you are supposed to checkout a dev branch anyway, right?

It is so important that I have to mention again that, if you rewrite history involving bookmark master, Hg-Git will record the changes while mercurial will not, so things will get really messy if you forget about that. Please work on development branches with bookmark master deactivated, when you finish all the history rewriting and rebasing and the changes are ready to be published, then and only then can you checkout master and push the changes to a git server.

Mercurial use explicit files to track some metadata, such as .hgtags for tags, it is of no use to git, but it is there, and the sha-1 hash for the same changeset is different in mercurial and git because they have different strategies in calculating them, so keep that in mind.

Conclusion

With Hg-Git, one can use mercurial as a client for a git server, and publishes mercurial repositories as git repositories at the same time, without much work, this is how I managed to publish my open source projects to both Bitbucket (as mercurial repositories) and Github. To people who prefer mercurial like me, but are forced to use git, it is the best of both worlds.