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. 🙁
13 replies on “What I miss after the switch”
The forest extension allows a behavior that is somewhat like svn:externals http://www.selenic.com/mercurial/wiki/index.cgi/ForestExtension
Using the pushlog you can list checkins by the date they were pushed. You could list checkins by their commit date using local commands, but the information often isn’t that useful.
Merging requires a commit is by design… AFAIK every distributed VCS has that requirement, though some will do it more automatically than others.
I think you want `hg revert .` not `hg revert -a`!
As for directories, because you have all the history locally, it doesn’t make a lot of sense to just check out a specific directory. Although archiving/tarring just specific directories does make sense… somebody should fix that!
On directories: cloning a single directory wouldn’t make much sense. What if someone in the central repo moves a file from Dir1 to Dir2 and you only “cloned” Dir1? I think that not being able to clone a single directory is a logical consequence of hg being a DVCS. With clone, you do just that: you clone the entire repo. You’d need a real, cvs-like checkout to do what you want, I guess. But then again, this wouldn’t be DVCS any more.
> What if someone in the central repo moves a file from Dir1 to Dir2 and you only “cloned” Dir1?
And what SVN is doing in such case? It just removes the file from it. I don’t see it as a problem.
>”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).”
Don’t know if this is a right solution?
For ex, instead of:
http://hg.mozilla.org/mozilla-central/file/8dcbd3d42d68/README.txt
we’ll use:
http://hg.mozilla.org/mozilla-central/file/tip/README.txt
Re: merge commits: I’ve actually been having good luck with hg transplant (= git rebase). It attempts to re-apply your commits against a different head, so I use it to update my local commits against upstream. Same merge algorithm, but in smaller chunks so I can deal with breakages easier (and no extra commit if all goes well).
Been using git on Windows, too… Seems pretty nice, so far, feels more mature than hg, with some different architecture (doesn’t assume commit all changes, for one). Last I checked though, git-svn was too slow to be useful there.
Re: hg.m.o links: http://hg.mozilla.org/mozilla-central/file/tip/configure.in
I also wish for partial pulls; in fact, I want to be able to forget old history too. (I don’t care about things older than a month; I can look at the upstream repo for that if necessary…)
It’s always the case that some parts of the versioning control system show up in how you layout your repos.
svn:externals kind of replicates soft-link functionality for those OS’s that don’t do it natively.
I suspect a more hg friendly layout would put all the modules in one repo and use real soft-links, but then it wouldn’t play nice on Windows.
I’m the hg developer mostly responsible for hgweb, so I’m always interested to hear your qualms. (I’m also regularly around in #hg on irc.mozilla.org if you want to talk.)
First off, we know that something like svn:externals would be good, but this is certainly not a trivial thing to accomplish. I can happily say that someone is currently working on a new extension that we may be able to integrate as soon as it gets good enough.
As for cloning specific directories, this stuff doesn’t always make sense in a DVCS. For example, how will you merge two heads that have disparate changes outside the cloned directory? Having said that, we have some code working towards this and are certainly aware of the feature (we call it ‘narrow cloning’, as opposed to ‘shallow cloning’, which means pulling down only a recent part of the history.
I’d suggest the separate commit to merge is anything but a dirty hack. I’d say anything else would be a crutch. I’d encourage to play with hg more. Besides, I think git and bzr do the same thing here.
Of course, I especially care about your hgweb concerns. First off, the links that you describe are actually possible, I think. URLs for hgweb are made up of //. If you link to file//some/dir that should get you a directory listing for that revision. Use ‘tip’ for if you want to link to the latest version.
I have actually been moving the code to where it is easy to arbitrary diffs. Biggest holdup there is a good UI, which is not usually my strong suit. The revision numbers, if you want them, could probably be made available from the templates; since Mozilla uses their own templates, file a bug with mozilla in the HG :: Customizations component and it can get fixed fairly soon. Similarly, your workflow problem sounds like a templates problem (or maybe you’re clicking the wrong link).
The summary, too, is a feature of the templates. We think the summary is not ideal, and don’t use it in our most recent template sets.
Finally, I beg you to actually come into our community (bug tracker, IRC: #mercurial on freenode) and ask about your issues. Chances are some of them can get fixed soonish, others can be put on the agenda. Also, it would be in hg’s best interest (which I think in some ways would also be of interest of Mozilla) if there also came some positive notes about hg into the Mozilla community. While a lot of people actually like hg from what I’ve seen, the atmosphere around it is kind of negative, which is too bad. I really don’t think other DVCSs would do better on most of your counts (they would probably have many similar constraints and a bunch more nags that we don’t have).
> 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).
No problem. Lets try to change the last part here (“aa3c4d3fb3fc”):
http://hg.mozilla.org/users/zbraniecki_mozilla.com/silme/file/aa3c4d3fb3fc
to: “multilocale”, “trunk” or “tip” -> it works 🙂
Thanks for your comments.
I’ll update my post tomorrow.
I definitely didn’t want to say I dislike Hg. I’m just using Hg a lot recently and listed things that I encountered that were a problem for me. Main reason was hope that people will point out solutions 🙂
So Dirkjan, fear not 🙂 I love Hg and find it extremely useful and a huge upgrade not only for work on basic products, but a great stimulation for easy forking, and branching, and experiments. Its just that writing what’s GOOD about Hg to people who’re using it every day is not that big topic 😉
Yes, but cloning is supposed to give you the entire revision history together with the files, so if you were able to clone a single directory, how would its history look like in the case described above?
Stas: I don’t need this. i need a feature that allows me to get a directory from my repo and be able to update it to given revision/branch. That’s all.
It’s a very useful feature from SVN that I miss here :/
For the directory problem, I think that’s just old CVS habits. hg revert . is even easier to type than revert -a. hg commit . isn’t too bad either. For systems where changesets are atomic, I think it’s natural to default to working on the whole repo.
>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)
Inability to checkout/clone/get in any way a single file or directory from the repo is the one thing preventing me from considering distributed VCS’s. I’m not thrilled about SVN, but until they figure this out that’s what I’ll be using.