So, a few months ago Mozilla have switched from CVS to Hg. Initially, I was fully against this switch. As much as I hate CVS and consider it defective by design, I had really bad experience with Mercurial too.
Mercurial in Flock
Basically, in November 2005 I was a proud member of Flock team. One of the most frustrating things we experienced was CVS and as a small, open minded team in a storming stage of project we decided to skip the natural update to SVN and go for something far more challenging. We switched to Mercurial.
Mercurial 0.7 was an interesting piece of software but was simply not mature enough to handle the project. Except of many small issues (sometimes things went reeeaaallly slow) there were a few big ones including accidental revert of checkins on merge without any notice.
I believe the last one was an ultimate reason to accept a failure and switch once again. Trust me, we didn’t want to switch but we couldn’t afford waiting for all those little things to get fixed and having such experience we decided to go for a stable thing – SVN – with all its shortcomings well known and accepted.
Mercurial in Mozilla
Mozilla spent a reasonable amount of time investigating options across Revision Control Systems and ultimately decided to switch to… Mercurial. (IIRC the reason for not going to git was its performance on Windows)
Fortunately, Mercurial matured enough to fix many of the problems we faced at Flock and after half a year with it, we can say that Hg works for Mozilla fairly well. It definitely has a higher entry barrier, it has longer learning curve, its fairly complex (which is a major problem for non technical people facing it) but it is extremely fast and flexible. It is modern, it is distributed and it is progressing which gives it a promise of a bright future.
I must say that my particular favorite things are:
- distributed architecture. For an average human being with developer skills it means I can code on a plane, in a bus or while at my girlfriend’s aunt house (during an exciting evening of talking about her relatives) without a connection. All the work can be later synced back to main repository and the revision log of such thing is usable.
- speed. mercurial is fast, much faster than CVS
- file moving. There are many things CVS was missing, but I believe that “move” is the single most important one. Lack of “move” in CVS is extremely destructive because it builds a habit of not moving files around without a super serious reason. Clean code, sanity and readability is not super serious reason, and in result while in CVS world, your source code gets less readable in one more way. If you decide to use remove/add in CVS to mimic move you’re loosing the whole history of the file which puts the whole purpose of RCS in question.
- bisect. Ability to go revision by revision to track where the bug has been introduced is extremely useful addition.
Unfortunately, Mercurial is also carrying many shortcomings. Some of them are especially painful:
- No svn:externals. It’s becoming a major flaw to me. In MCS project we have tons of small modules that link to each other but should be stored separately. Many CSS/JS files should exist in one place and be linked from specific themes. Lack of externals is not only costing time (I have to apply patch against 5 places) but it also hits user experience (I cannot let someone just pull a repo, he has to manually go into one dir and pull another). It could really help out L10n repo to point to each external locale repo from l10n main repo.
- Mercurial does a poor job with directories. It may be a matter of habit, but it happened to me that I did “cd ./repo/dir1/dir2;hg revert -all” to revert the whole directory and got the whole repo reverted. Same with commits and other commands. I find it very counter intuitive.
- It also has a problem with pulling directories. I failed to find a way to get a particular directory cloned or pulled from a repository. In result directions for users are getting even more complex (pull this repo, then get this directory and copy it there)
- It requires a separate commit to merge. I’m not an expert, so maybe its deeply rooted in logic, but it looks like a dirty hack. (pull clone1, pull clone2, work on clone1, commit, work on clone2, pull to merge… commit the merge.)
Also, our hg.mozilla.org webview is limited comparing to websvn in many areas:
- you can only download full repo. If you go into particular directory and press “zip” or “bz2” you will download whole repozitory. wrong!
- you can only link to the whole repository or to particular revision. I need ability to link to “latest” revision of one file or directory (in a branch).
- you cannot diff between two given revisions (only diff to previous one)
- you don’t see the revision number until you open a diff to previous revision.
- you cannot list checkins for given time frame.
- search sux. only 10 results, no way to get more, not sure what it really includes in results and what not.
- workflow is screwed. When I’m viewing one file, and I click on revisions, and then browse, I land on the root of the repo for the revision, not in the file I’ve been viewing before.
- summary shows you whatever branch has been updated lately. It caused several localizers to get scared to death when they updated branch and saw it in what they thought will be tip. It’s very confusing and may cause people to react randomly.
Some of them are minor, some of them are major. I’m particularly desperate to find a replacement for externals and directory exporting cause its important to give clear instructions for MCS project, and without those two the instruction is getting long and clumsy. 🙁