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.
To share commits between friends one can use git format-patch/apply + email.
I also feel like I’m one of the only people who thinks Git’s CLI makes perfect sense. I wonder if my reasons are the same.
I just wish “git commit yetunknownfile” just added the file as well.
See I find it safe to only add files I explicitly say add and I would never want anything added. I use GIT for my configs in my home pages (Each distro has it’s own branch). I also use git as a one man work flow so I have a different view of git but man I love it.
I read a comment recently that criticized git for its bad UI, the author complaining that they shouldn’t have to learn a tool’s internals to be able to use it effectively. At first, this seemed like a valid criticism to me, since, while I like using git, I only began to feel confident with it after spending some time learning about its internals.
I ended up changing my mind, and, I think, coming to a similar idea as mitsuhiko. I like using git because of its internals. I want to know how my version control system works. I find git’s way of working to be pretty nice, and easy to reason about.
When I’m opening, saving, renaming, moving, and copying files, I’m thinking about what’s happening in the OS and on disk. And I like that. It gives me confidence. When I’m fetching, committing, merging, branching, and pushing, I’m thinking about what’s happening in git’s data structures and on disk/over the network. I like that too.
That may have been me.
With git on the other hand even the first page of the tutorial has a direct link to the internals chapter of the git book which explains the internal implementation of git.
That right there is why I don’t like git.
Yeah that sounds right! haha. Still see where you are coming from, still feel the same opposite way :)
One of the most useful starting points for me was Jim Weirich’s “Source Control Made Easy”:
By understanding the underlying concepts first, it makes it much easier to transition to “the git way” than trying to shoehorn your old version control system methods into it.
Full Disclosure: I used to work with the Prags producting podcasts, but had purchased this screencast prior to working with them. I also do not receive any royalties or payment for recommending their content. I really do think it’s great :)