Over a million developers have joined DZone.
Platinum Partner

Switching to Mercurial

· Java Zone

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.

When I first heard that NetBeans and OpenJDK were going to switch to a version control system I'd never heard of called Mercurial (aka Hg) I had some reservations.

Well, this weekend, we did the switch - all the sources of NetBeans are now housed in Mercurial at https://hg.netbeans.org - and I also spent Saturday setting up my own Mercurial server at home from scratch and putting a bunch of code in it and working on it. It was incredibly easy to set up!

To my surprise, I'm really liking it a lot. Here are some of the reasons:

  • Checkouts are much faster than CVS - and that's pulling down the entire history of the repository, not just the trunk - so it's faster for pulling down more stuff
  • Since you have the whole history, you can do any sort of historical diff, merge, patch or rollback you want without a network connection
  • If you want to try something that you might want to roll back, cloning your local repository is very, very fast (Mercurial takes advantage of Unix and NTFS hard-links, so you're not copying tons of files)
  • Setting up a repository is as simple as typing 'hg init'
  • Setting up Apache to serve it is pretty darned simple; in a pinch you can just type 'hg serve' to move some stuff between, say, a laptop and desktop (ever set up a CVS server? Or just tried to find documentation on how? It ain't pretty)
  • Creating a branch is just cloning your local repository (more on that in a moment)
  • It's not about file versions, it's about one commit being an atomic unit (ever needed to figure out from CVS, gee, I need version 1.52 of this and 1.3 of that - files are just the wrong unit of graularity)
  • Each commit can be uniquely identified by an SHA-1 hash
  • If you know the hash of the commit (easy to get), you know what versions of everything else it was built on top of

Things that are different than CVS or Subversion:

  • Mercurial is a distributed VCS. You have a local repository that you commit a changeset to. Then you push changes to some other repository (might be a local path or a http or ssh url), or you pull changes from a remote repository.
  • No repository is king - there is no concept of a master repository except by social agreement that that's where everybody puts stuff
  • If the network is slow, you can easily have a periodically updated local mirror
  • Easy to chain repositories - push to a repository that runs tests or some other analysis and then if they pass pushes the changes on

Things that seem less good than working in CVS:

  • If you want to work on a branch in public, you need to get the repository from that branch up on the web somehow (not that hard to make this easy, just the social risk that old, long-since merged branches will pile up in such a tool and make things hard to find)
  • Because everything lives and dies by hashes, if someone pushes changes to files you haven't changed, and you want to push changes to other files, you have to pull all the changes from the remote repository before you can push yours. One of those things where it's fine unless everybody flushes the toilet at once, which might happen around the end of the day when it comes to pushing changes.
  • The NetBeans integration modules isn't quite ready for prime-time (but with 200 developers using it daily, I expect it will improve quickly)

All and all, I am very happy about this change. Have you used Mercurial? What do you think? I'm sure there are gotchas I haven't forseen - anything that changes workflow for a few hundred people is disruptive. But so far it's been a remarkably smooth transition.


The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}