Switching to Mercurial
2014-11-15
UPDATE: I now use Mercurial on the client side (i.e. everything I do
locally involves hg
) and Git on the server-side. It just makes it
easier to mirror to Gitorious, GitLab, etc. You can view all the
repos at http://kaashif.co.uk/code.
Earlier in the year, I was getting curious about version control
systems other than Git. Git was my first VCS, and the one I was most familiar with, but I didn't want to be...locked in (cue gasps). Obviously, there isn't any potential for actual lock-in, but there is a Git (and even more worryingly, a GitHub) monoculture developing that I don't want to be part of.
I could lie and say that it was for practical reasons, but at that time, I was concerned with the fact I was becoming mainstream in my choice of VCS. The first alternative I looked to was Darcs.
Migrating to Darcs
When I switched to Darcs, the first thing I had to do was convert all of my repos from Git. This posed a bit of a problem, as 99% of guides are for converting from Darcs to Git, which is obviously not what I want. In the end, I just settled for:
$ for repo in *; do
> (cd $repo; rm -rf .git; darcs initialize);
> done
That's not ideal, because I'm essentially nuking all of my history for no reason, but as a lone developer, it doesn't matter. So that was fine. I guess I can't hold it against them that no-one wants to migrate to Darcs. Well actually, I can, but I chose not to.
Eventually, after setting up a darcs account and pushing all my repos to my server, I decided I wanted some sort of cgit-esque web interface. I was pleasantly surprised to discover that you don't necessarily need anything special to browse Darcs repos, you could just use a normal web server's directory listing capabilities. I did that for a while, but it was pretty bad. In the absence of any bundled solution, I took to the web and found darcsweb, which wasn't too bad. Sure the last release was in 2008, but that means it's feature-complete and mature.
Darcs: the good, the bad and the exponentially complex
Darcs is good. It's written in Haskell. Everyone loves Haskell. You know who loves Haskell the most? The guys who wrote the Glasgow Haskell Compiler. But, uh, they don't use Darcs, they use Git. They used to use Darcs, but it's apparently too slow for them.
I didn't think that would affect me: GHC is an absolutely massive project.
I was wrong.
After trying to commit the entirety of the OpenBSD source tree (a VCS should be able to handle this) and doing some merge-fu, it was time to go back to Git. Evidently, Darcs' merging algorithms and patch algebra needed some work.
Why switch?
After the recent news that the Go team decided to switch to Git, I decided once again to switch away from Git. This time, I wouldn't come back. The obvious choice was now Mercurial: it is widely touted as being easy to use, competetive with Git in terms of speed, and overall, it's supposed to be actually usable. Also, Mozilla use Mercurial for their massive projects, so at least someone other than the creators use Mercurial.
You might be wondering why I told that story about Darcs. Well, it's mostly just so that you have more than 2 data points to compare. Let's get comparing, then.
Mercurial is really, really easy
Git has a propensity for being really hard to use and cryptic. There's the classic example of reverting a file. How do you do that?
(Git)
$ git checkout file
(Mercurial)
$ hg revert file
Well I suppose you'd eventually remember that checkout means
revert... not that bad, right? Well, putting aside the fact that there
exists a git revert
command that does something completely
different, sure. It's not that bad.
Let's look at reverting to the last commit.
(Git)
$ git reset --hard c0mm1th45h
(Mercurial)
$ hg rollback
I know, I know, I've cherry-picked examples that paint Git in a bad light. Whatever fruit I've been picking, the fact is that Mercurial is a lot easier to use, and a lot harder to mess up than Git is.
Also, it's shockingly easy to convert a Git repo (or any other repo) to Mercurial. Let's say there's a repo in "myrepo":
$ hg convert myrepo
Then there'll be a converted Mercurial repo in myrepo-hg. That's fantastic!
So, after some quick Googling and playing around in test repos, I converted all of my Git repos and pushed everything to BitBucket. But I needed to set Mercurial up on my server.
hgweb
Hgweb comes with Mercurial and is, as the name sort of suggests, the gitweb of Mercurial. It was a breeze to set up, you just fill in the path to the config in the script itself, set it up as a CGI script, and write a config file. Mine looks sort of like this:
[paths]
blog = /home/hg/blog
tau = /home/hg/tau
And a load of other repos. You can take a look at http://hg.kaashif.co.uk.
Wow, that was barely a paragraph. Mercurial really is easy!
Committing to BitBucket from a hook
I really like it when I can self-host 90% of everything and just use GitHub, Gitorious and now BitBucket as a glorified backup. I already have an online repo browser and SSH server, all I need is for my server to push to BitBucket whenever there are incoming changes.
This was surprisingly easy. All I had to do was edit the ~/.hgrc of the hg user and add a global hook and path to a script:
[hooks]
incoming = /usr/local/bin/push_to_bitbucket
Now, when there are incoming changes, they'll be received then pushed to BitBucket. Well, they will be after I write the script:
#!/bin/sh
hg push ssh://hg@bitbucket.org/kaashif/$(basename $(pwd))
Within 30 mins, I had everything set up. A lot quicker than I was able to do it with Git, although I suppose I now have the benefit of hindsight and experience.
I've even heard that with hg-git, I never have to use Git, even when upstream is Git-only. Maybe this time, my migration will be permanent.