Haha, I spurred this debate with mitsuhiko over IRC yesterday. I was arguing with him over git vs hg yesterday, and this blog post is obviously his retort. Here is my defence of Mercurial:
Mercurial’s design aims to welcome people who come from other VCSes. It started being welcoming to CVS and SVN users, and its CLI mimicked those, as well, as a few ideas of Bitkeeper. Git’s initial design was very bitkeeper-like too, such as branching-by-cloning being the only way to branch. Nowadays, Mercurial also makes some concessions to git users.
Despite its various sources of inspiration, Mercurial works hard to keep all of these ideas consistent. Commands rarely grow new options. Many deviations from core functionality are first tested in optional extensions for a long time before going into the core. Lots of time is spent bikeshedding what a command’s name should be, and what language the documentation should use. Consistency is very important. Backwards compatibility is tantamount. The CLI is the UI and the API.
A thing git is often lauded for is the simplicity of its internals, which are frequently deemed to be as simple as to not be internal at all. Despite being a binary format, Mercurial’s revlogs are also approximately simple, which is why people sometimes write parsers in other languages.
But Mercurial is a lot more than just git-with-a-nicer-UI. There are many exciting features in Mercurial, features that I don’t think will ever make it into git because they are just too different from the way git works. Mercurial Evolve really changes the way we collaboratively edit commits. Templates and revsets can be combined to program interesting extensions. New extensions can scale Mercurial into gigantic repos.
And because I think these ideas are so great and must be explored and improved, I will keep using Mercurial, teaching Mercurial, and improving Mercurial
features that I don’t think will ever make it into git because they are just too different from the way git works
Correct me if I’m wrong, but there’s nothing (except their famous silly “everything not referenced by ref is garbage” convention) that prevents git to have phases or changeset evolution or mercurial-like branches.
Cultural inertia, mostly. The git people would refuse most of these changes.
The phases idea was actually proposed for git’s GSoC 2012, but was never picked up. Mercurial-like branches can be done with git’s extra fields, which is how Kiln Harmony does it.
Evolve is the biggest difference and the hardest to fit into git’s storage model and existing UI. I’m not sure where in the git storage model to store obsolescence markers. I suppose they could be extra blobs?
I’m not sure where in the git storage model to store obsolescence markers
why, “extra fields” don’t fit here?
No, obsolescence markers are not associated to a particular commit’s metadata. You don’t want a commit’s hash to change when it acquires new obsolescence markers. And a marker typically involve two or more commits, which can mark which commit replaces the other(s). Yes, a marker can have several outputs: consider folding, which produces a single commit that replaces at least two others.
Further, the same commit can be replaced by more than one commit. Bob replaces X with Y but Alice replaces X with Z. This is called divergence and is a kind of instability that hg evolve must handle.
Although it usually is, the obsolescence graph isn’t even a DAG: it’s impossible to ensure it to be a DAG because of the D in DVCS (or unless you introduce a meta-meta history, and then it’s meta all the way down).
So, yeah, evolve needs .hg/store/obsstore in Mercurial. I don’t know what an equivalent would be in git.
Mercurial is my git alias, via hg-git. Kinda funny that we already have commands in hg like
branchto make a branch andbranchesto list them (same with tags and bookmarks), as well asuncommitandamendcommands.+1 here. Only small downside is
.hgdirectory contains both hg and git repositories