Browsed by
Month: August 2011

Mercurial Frustrates Me

Mercurial Frustrates Me

Maybe I’m just used to having too much power at my fingertips. Git was designed, from the ground up, to provide operations to do absolutely anything to a repository, right down to the most basic level of manually creating individual objects in the repository. Using user-visible command-line tools that can be operated from scripts. It is literally possibly to reimplement most of the user visible Git commands (such as “commit”!) using shell scripts and some of the more-basic Git “plumbing” commands.

So, there’s no surprise that Git commands support special script-friendly output modes. A good example: git log --numstat will print out a summary of the changes in a commit in a parser-friendly tab-delimited format. Mercurial doesn’t have this option. (Someone wrote a patch to add it, but it was rejected!)

And then there’s the issues with speed. I’m writing a script that generates a summary of the differences between two branches based on which commits have been merged into each branch.

$ time git log --pretty=oneline --numstat brancha..branchb
real 0m1.081s

So, about one second. Not bad for a command that’s summarizing around 400 commits from a 250 MiB repository. Lets see if Mercurial can keep up:

$ time hg log -r "ancestors('branchb') - ancestors('brancha')" --template "{node} {desc|firstline}\n" --stat
real 3m51.994s

Ok… That command took over 230× as long in Mercurial as Git. Amusingly, the same repository in Mercurial is around 500 MiB – twice the size! (For the record, it’s mainly the --stat that slows it down. If I remove the stat, Git takes 0.167s, and Mercurial 0.421s). This is completely unusable.

So, why is Mercurial around 200× slower to calculate the differences contained in a commit? I don’t know. But they really should fix it.