Git's concept of branches as simple names for commits, and the ability to switch branches really easily within one checkout (rather than encouraging the use of multiple working directories) helped hugely. Mercurial grew the ability to do git-style branching later, but git had it from the beginning.
Git has always treated performance as a first-class feature, and that has enabled certain types of workflows that Mercurial makes painful. Git is fast enough that many things don't feel like they take any time at all.
Git integrated first-class support for carefully constructing and reworking a set of patches to be sent by email. Mercurial again eventually grew such support, but early on, it was much more insistent that all branches must be kept around, and by the way are you sure you don't want to push your development branch experiments up to the server and keep them there forever since you haven't merged that head into the mainline?
Even later on, mercurial had more of the functionality people wanted but relegated it to "extensions", while Git shipped it out of the box.
Take a look at https://walac.github.io/mercurial-for-git-lovers/ (from 2015) for just one of many examples.
My understanding is that while Git stores a tree of objects indexed by hash (and then packs them into packs along with an index, which can be repacked arbitrarily later on), Mercurial's primary data format is a log-structured list of revisions as deltas.
The underlying data structures used are different, but considered an internal detail, so could be changed in the future. Today, most data is stored in a "revlog", where data can be either be stored (compressed) directly or stored as a (compressed) delta against an earlier version. Deltas may be chained. The index consists of fixed size records, which gives fast lookups, which are also linked to global revision numbers so that you can eg quickly find the commit based on a specific file change.
Obs: This is based on attempting to re-implement the basics of Mercurial from scratch.
So while it might be obvious for you why Git became most popular, I believe that today, it continues to be that way mostly because of GitHub.
As a heavy Mercurial user, but only for the last couple of years, I'm confused by this one. You can just as easily switch between branches (in the Mercurial sense) and bookmarks (which are Mercurial's name for Git-style branches). How did that used to be different?
In fact one of the nice thing about Mercurial is that you can easily switch to any commit and you don't need to choose between a hard reset and a detached head, because you can always make a commit anywhere (multiple heads for the same branch) and it will never get garbage collected (a foreign concept in Mercurial). Mostly this is good because you simply never need to understand what these concepts mean, which it turns out are not fundamental to DVCSs. But also this makes a neater alternative to stash (although stash is also available): just commit your half-finished changes, mark the revision "secret" (which means it won't be included in any push), then switch to another revision. You can always strip or rebase the revision later, so long as you haven't pushed it (admittedly these actions do require extensions, but they're included with all Mercurial installations).
This might be mainly habit and familiarity with a different tool by now, but to me it's simpler than equivalent Git workflows as there's less ceremony involved to start working and there's no fear around accidentally losing commits because they don't belong to a branch (I kinda hate having to go into the Git reflog to find commits that are temporarily lost because they don't belong to a branch).
I've used Mercurial from the very beginning, the branches are great and bookmarks are fine. I see no reason why you wouldn't use them.
We as a community of developers have learned a lot about the power of DVCS since git and mercurial got started. I'd say even the developers of those two tools have learned a lot since then.
So are we going to have something better than both hg and Git? There hasn't been any new DVCS for a long time.
It's a pity, because I like its technical ideas.
Especially the Windows port seemed rather prone to corruption.
Quite the opposite of my perception.
I started with git. Then I got a job and for a while I worked only in Windows. At the time, I looked into git for Windows, and while everyone said it was stable, everyone also said that it was unofficial - the Git development team had stated clearly they were not interested in maintaining a Windows version.
I didn't want to be in the position to justify an unofficial tool to my employer, so I looked at Mercurial - Windows support has been in there since the first day. So I switched to Mercurial. In almost a decade of using it on Windows, I have never had any problems.
Mercurial is great - I've never come across a use case where git is clearly better.
This results in 90 minutes of waiting with hg pegging one CPU core (CPU-bound, not disk-bound!), then a few minutes of hg actually writing files, then the actual build taking 60 minutes.
In the git community, it was always taken as a sign that they were doing something right that `git clone` was faster than `cp -r`. I'm having a hard time not taking it as a sign that Mercurial is doing something wrong that `hg clone` is so much slower.
edit: The saying was that `git checkout` is faster than `cp -r`, not that `git clone` is. The sentiment stands.
When you cp an active git repository you receive an identical file state; when you git clone you receive only what is necessary. Old objects, reflogs, et al aren't in the clone. A clone of an existing local repository may also make hard links, if your file system supports it.
https://apenwarr.ca/log/20080121 (some more nuance)
--local, -l
When the repository to clone from is on a local machine, this flag
bypasses the normal "Git aware" transport mechanism and clones the
repository by making a copy of HEAD and everything under objects and refs
directories. The files under .git/objects/ directory are hardlinked to
save space when possible.
If the repository is specified as a local path (e.g., /path/to/repo), this
is the default, and --local is essentially a no-op. If the repository is
specified as a URL, then this flag is ignored (and we never use the local
optimizations). Specifying --no-local will override the default when
/path/to/repo is given, using the regular Git transport instead.From what I could tell, whatever the slow part is, it wasn't parallelized at all; of 16 cores, 15 were idle, and 1 was pegged at 100% (and very low disk-wait).
I've been meaning to dig in to this more. I'd tried adding --stream, figuring that maybe it was re-compressing the entire repo; but that just lead to a warning about "server doesn't support streams" or something like that. I'll definitely try ygra's suggestion to try --pull, and if that doesn't yield good results, I'll actually dig in to the sources and see what's going on.
In any event, if you're enthusiastic about this kind of thing, we'd love to have more eyes on making hg checkouts consistently fast, even in the face of filesystems undermining those efforts. ;)
Mercurial usually had the speed advantage but then git came along and wasn’t written in Python. Speed wise it blew Bazaar and Mercurial out of the water.
It was harder to learn for someone used to svn, perhaps, but the sheer weight of both Linus and Linux made it hard to ignore.
I think GitHub deserve a lot of the credit for git’s omnipresence, though. With Launchpad our aim was to create something bigger than “just” a code sharing site and fairly or unfairly both Launchpad and Bazaar were seen as too close to Canonical. Whereas GitHub picked up the mantle that Sourceforge had dropped and made something way more collaborative than Sourceforge but held onto the idea of being a neutral third party.
RCS -> CVS, CVS -> SVN, SVN -> Darcs, Darcs -> Mercurial, then Mercurial -> Git.
Bazaar I had to use for interactions with Ubuntu, but never in a serious way. Similarly I used a few other things such as Visual Source Safe (shudder), SCCS, and even BitKeeper, but I think they were used quite shallowly.
Benchmarks for this are hard to come by, and are for versions that are considered quite outdated now. But from what little there is, there wasn't that much of a performance difference between git and hg. For example, see this: https://www.draketo.de/proj/hg-vs-git-server/test-results.ht...
As for benchmarks, I don’t have any but there’s plenty of anecdata elsewhere in this thread that echoes the idea that git had significant speed advantages over both bzr and hg.
I think it's more that Launchpad is terribad. No matter how much I used it, I struggled to get to the code so I could read it. It looks like it's been somewhat fixes now with a small "Browse the code" link on the project landing site. It used to be like 4 clicks if you knew what to look for.
And when I used bazaar (on Arch in 2004 trying to contribute to Exaile), it would pin a core and make no progress. I didn't look at it again.
Mercurial was ahead of git for a long time as far as usability and documentations were concerned. I still think it's a better match than git for many uses cases. Mercurial makes the simple stuff simple and the complicated stuff complicated (although still achievable), whereas git is more of a mixed bag in my experience. Git was superior for very large projects with many contributors working on completely different features and sending each other patches by email (e.g. the Linux kernel) but in practice 99% of projects, both FLOSS and corporate, don't have this profile. Git is a formula one, mercurial is more like a comfortable Sedan, so to speak[1].
I think git made it mainly because it could boast hosting the Linux kernel development and all the cool kids were on github.
[1] Which reminds me of this "Git is MacGuyver, Mercurial is James Bond" comparison which is probably widely out of date by now: https://importantshock.wordpress.com/2008/08/07/git-vs-mercu...
Of course, if you understand the underlying data model, they seem far less arcane, but that's the problem with Git that Mercurial doesn't have - you really need to understand what's happening under the hood to get proficient at it, whereas Mercurial has a far saner interface that hides the internals under a better abstraction.
I just know on my team or 5 much less technical people, the concept of version control and how to do operations in Mercury was near impossible and it fell on one person to manage merging files with master.
Also, this was a distance learning course where the head institution (MIT Media Lab) was keeping a central repo of every location's additions, and the changes made the repo so big that we had hard caps on how much data we could upload.
Later on, it fell on me to introduce git to some colleagues. Just walking them through 'checkout','branch','merge','push','pull' got them on their feet and contributing to a repo. If they hit a wall, I could help detangle the knot, but at least we were in it together.
* hg log by default doesn't tell them anything about the current code they're working on; it's just a dump of everything. To get the history of the current working copy they need to pass -f which they are learning in other contexts means "do something unsafe".
* hg gives commits sequence ids that can locally be used in place of the commit sha, but must never be shared across repositories.
In practice at Mozilla I have seen people run into both these issues, causing much unnecessary confusion.
Basically the problem is that unlike Mercurial branches which are actually branches while git branches are just a pointer to a particular commit. That pointer has no knowledge about what other commits are in the branch and the pointer can be moved anywhere across the tree (even to unrelated commits) with ease. Apart from the reflog, it's basically not possible to ask about the set of commits in the branch. The best you can do is never ever move the branch pointer except forward and make a note of the branch that your branch branched off of so you can do things like `git diff my-branch..parent-branch` (`hg diff -b my-branch` iirc). And this is just one of dozens of git warts.
1. Network effects of github becoming popular. 2. It's faster. 3. Linux uses it and it was written by Linus (must be good in some people's minds).
I think since then many people have realised that Linus was right and that git is good, but it just wouldn't have gained so much momentum without Linux.
Even considering the additional overhead, we switched to git after a few weeks since the repository was constantly broken, and the two of us that knew git and SVN were desperately searching for the consistency and tools we had in git. At least we could support the team from there on and make it work for them. Not the ideal solution, but the best available to us.
So I totally understand why git is more popular than hg. Until hg could be considered mature enough for larger teams, git already had a huge following, IMO.