Five Features from Mercurial That Would Make Git Suck Less

posted Thursday, July 16, 2009 by topfunky

Some of the smartest programmers I know are also the most well rounded.

No one can deny that Why the Lucky Stiff is a strong advocate for Ruby, yet he knows Python well enough to write a bytecode converter that targets it.

Last year I switched to zsh because Christian Neukirchen recommended it, yet he is conversant with the next version of Bash, comparing and contrasting their features with ease.

Over the last few weeks I’ve been using the Mercurial distributed source code management system. I had encountered it when checking out a few open source projects like BWToolkit and wanted to become more familiar. Most blog posts that champion Git feature a few Mercurial commenters claiming that “Mercurial is easier to use.” Is this true? Why do they say that?

This isn’t an attempt to convince you to use Mercurial exclusively. And I’m intentionally skipping any mention of Mercurial’s shortcomings. I want to see these features in upcoming versions of Git. If I’ve missed something and that feature is already available, then I’d love to know about it! Leave a comment even though it won’t show publicly (I’m dealing with spam problems).

So here are 5 features Git should steal from Mercurial.

An Intelligent Setup Command

Mercurial (command hg) has a much smarter command for creating repositories. You can create both a directory and initialize a new repository with one command.

hg init my_project

Git assumes that you are in an existing directory and will squawk otherwise.

Accomplishing this in Git would take something like this:

mkdir my_project
cd my_project
git init

In addition, you can clone an empty repository. Imagine creating a new repository on GitHub and being taken immediately to your new project page with a link to clone the repository. That’s the experience you get with Mercurial.

No local setup is required. No editing of your .git/config file. Just clone and start adding files.

Put these together and you get a Bash function like this to create a private remote SSH repository and clone it locally:

function new-hg {
  ssh user@example.com "hg init $1" 
  hg clone ssh://user@example.com/$1
}

Call it like this:

new-hg my_project

Right now Git requires that you commit one changeset before it will let you clone a repository. A simple solution is to add a .gitignore to the project. In fact, that would be a great feature request for the GitHub workflow!

Branches Everywhere

Git makes branching easy. Much easier than it was with Subversion.

But good luck trying to use those branches! Once you go beyond the local machine you’ll encounter cryptic commands abounding with switches and options that are weird but commonly used:

# Delete a Git branch
git push origin :refs/heads/feature-tweak

Mercurial branches are not only easy to make, they are also easy to use! They go everywhere the repository does. You don’t have to worry about tracking branches or weird pushes to get them onto your remote repository.

hg branch feature-tweak
hg commit
hg push

Once you’re done, close the branch and they disappear.

hg commit --close-branch

I’m sure someone will counter with the argument from Linus that this requires coordination between developers to avoid branch name clashes. First, this isn’t really a problem unless you’re on a large team that shares a single repository.

And even in that case, why not use your name as a namespace?

git branch topfunky-feature-tweak

Git branches are already separated by the name of the remote repository. Why not just prepend the developer’s name to it as well? Then let me checkout a branch with that identifier and commit to it.

git checkout topfunky/feature-tweak

Quick Local References

Mercurial provides a nice local shortcut for referring to commits. Instead of making ASCII art with specifiers like master^_^, you can use a nice integer:

# 18:a432bc
hg checkout 18

These numbers don’t travel across clones, but they make it much easier on the local machine.

Sensible Defaults

You can use Mercurial for a long time without using command flags. Most commands can be used without requiring knowledge of the underlying guts of the SCM.

hg revert .

Compare this to:

git reset --hard ORIG_HEAD

Commits happen Subversion-style. Yes, this is a feature! No need to add files before every commit or use a flag. Just commit and any changes since the last one will be included.

The incremental commit feature of Git has always confused me. I understand the theoretical beauty of being able to commit just one part of a file, but that means you’re committing a changeset that you’ve never used, never run tests against.

Easy Serving

Serving files happens easily without any arguments via the built-in webserver:

hg serve

You can visit the site at http://localhost:8000. As a bonus, you can clone it directly over HTTP:

hg clone http://localhost:8000 my_project

Again, simple and straightforward. No post-commit-hook tweaking is required.

Conclusion

I’ve intentionally left out any of the nasty bits of Mercurial, preferring to feature Git’s instead.

The good news is that most of these features could be implemented as surface-level improvements. I already use a handful of scripts to manage the otherwise unsavory tasks involved with using Git daily. Perhaps a few more could make it even better.

Product Placement

My pal and co-worker Dan Benjamin has prepared a fantastic PeepCode screencast on Mercurial. I assume that most readers of this blog are probably comfortable with Git. But if you’re like me and are continually looking for ways to improve your tools or adopt new ones, I think you’ll find it satisfying.

Leave a response

Your Comment

Nuby on Rails

Geoffrey Grosenbach / Ruby / Code / Graphics / Design / Rails / Merb / Javascript / CSS

Manufactured with

Subscribe

Subscribe (RSS)