"In my time with Mercurial, I have seen it grow in fascinating ways. These include the concept of changeset evolution coming to life and the announcement of both Facebook and Google choosing Mercurial over Git. The future of Mercurial is that of scalability and because of that, I believe the best days of Mercurial are ahead."
Is it time to give Mercurial another shot? I first migrated from SVN to Mercurial way back when - but after the massive increase in Git's popularity I bit the bullet and switched.
There exists no easy tutorial, that takes a beginner up to speed with git. You need to read almost a book length of material and familiarize yourself with some of the git's internals, and to some extent build your own mental model of git by experimentation, before you can use git without regular wtf-moments.
Well, there is also no tutorial that would provide the same level of understanding of the internals of Mercurial, but by some magic it seems that beginners do not need to acquire the same depth of understanding of Mercurial that they need to acquire about git, before they can start to work with Mercurial without wtf's and frustration.
Once you have a solid understanding of how DVCS's work, you can use both Mercurial and git without problems. But if you need to bring a bunch of beginners up to speed, somehow it goes easier with Mercurial.
At least, this is my experience. If someone else has experience in training teams to start using a DVCS, and has compared both git and Mercurial, and has opposite experiences, I'd be interested to hear.
I used git for a couple of years and definitely had regular wtf moments. Switched to Mercurial and they just went away.
The complexity and counter-intuitive (to me, at least) nature of git's model was a major barrier to entry.
I still use git now and then because github is so popular, but for a small team on a moderate-sized project I really prefer Mercurial for its ease of use.
I simply don't agree with this. There's nothing wtf about git add, git commit, git push. Those are the commands that normal developers use. Maybe git reflog has issues but 90% of people are never going to come across them.
1) So you can revert the merge very easily.
2) Merging without a commit.
3) A branch on a remote server that you have a copy of locally and you want to keep track of the status of remote against the local copy (who's behind and who is ahead?).
This is my basic understanding in terms of how I use git. I like Mercurial too and don't have a horse in this race.
I use git every day, all day at work. It is absolutely integral to my workflow, and the only thing I know about its internals comes from people posting about them here.
Needing to know anything about git's internals to be able to use git is FUD.
It has greater extensibility (both in protocol and the code itself), which is why Facebook and Google are looking at it in the first place: it's possible to hook into it in such a way that you can make it scale to ridiculous sizes (see e.g. https://bitbucket.org/facebook/remotefilelog) cleanly, in a fully backwards-compatible way, without forking the product. So it's worth looking at for at least that reason alone.
Beyond that, though, the team itself is leveraging that extensibility to continue to evolve Mercurial in new directions. Years ago, I was able to ship a third-party largefiles extension that worked similar to the GitHub external files thing launched a few weeks ago, and was able to get it integrated into Mercurial easily, where it was heavily used for years by people in the games industry. The team took "bookmarks" (Git-style branches) under its wing when they proved valuable, and have now added a ton of behavior to improve bookmark workflows.
They can even add huge new features. the big one that Git lacks is changeset evolution. Evolution allows you to get all of the benefits of rebasing and squashing, and all the benefits of a traditional DVCS merge-based workflow. Specifically, you can see all the previous versions of a given changeset, but those versions don't need to clutter up the history unless you're specifically interested. This means you're dramatically less likely to lose critical forensics information over the course of developing a new feature, and much more likely to be able to sanely see where, over the course of several rebases, you mucked up how a chunk of code actually worked.
> it's possible to hook into it in such a way that you can make it scale to ridiculous sizes (see e.g. https://bitbucket.org/facebook/remotefilelog) cleanly, in a fully backwards-compatible way, without forking the product.
That's not entirely true. For instance, some of the scaling is going to require a new manifest format that is not going to be backwards compatible.
Oh god, revsets. When i was able to use Mercurial (via hgsubversion and hg-git), i used revsets constantly, to ferret out all sorts of useful knowledge from the repository. My Git-using colleagues thought i was some kind of wizard. I switched jobs, and now i just use Git. I miss revsets so much.
In that lightning talk, were you actually typing or were you playing an accelerated recording of you typing previously? Cause it seems like you type at something like 300 wpm or something insane like that!
Performance on huge monolithic repositories like the ones Facebook, Google, and Mozilla work with is actively considered by the mercurial developers when integrating new features.
Aside from what others have mentioned, the biggest thing for me personally is hg share, i.e. the ability to have two or more independent checkouts of the same repository. Git does not really support this. Your options are (1) git-new-workdir, which is not safe and can lose data and (2) doing a complete clone, which is cumbersome, because you can't directly diff/merge against branches in the other repository, but have to push/fetch first.
Disclaimer: I'm one of the strange people who (by preference) still uses Bazaar over Git and Mercurial whenever possible, so that may skew my preferences.
To add to the Google bit, from Facebook's F8 there was this interesting tidbit (source[0]):
> Quote from Google: "We're excited about the work Facebook is doing with Mercurial and glad to be collaborating with Facebook on Mercurial development." (Well, I guess the cat is finally out of the bag: Google is working on Mercurial. This was kind of an open secret for months. But I guess now it is official.)
As well, if you search the Mercurial-devel mailing list[1], you'll see that Google engineers has been committing to Mercurial for a bit now. (Looks like they started in Aug 2014, and really picked up in Nov 2014).
TortoiseHG. SourceTree is getting to be OK, at least on windows but git gui apps suck. And if you are doing anything non-trivial and non-automated then gui SCM clients are just fine kids.
I heard that Facebook picked Mercurial because it was easier for them to make it work at their scale.
On the other hand, the company I currently work for also uses Mercurial, but all the developers besides maybe the founder (I haven't asked) prefer Git. I don't know the specifics about why everyone feels that way but from what I gather it has to do with branching being easier.
I've come to the conclusion that git got branches right. The idea of permanent metadata for branches is appealing, but repository-wide single namespace is bit of a PITA in some circumstance. Mercurial's bookmarks are the same as git's branches, but Bitbucket support is lacking.
The other big thing git has is startup speed. Python is slow. Something like chg helps, but it's a workaround.
I am not really happy with either Git's or Mercurial's solution.
Git's branches introduce too much fragility in the system for end user consumption (because branches are responsible for both naming and keeping commits alive) and do not allow you to describe sets of commits (nor is there an alternative feature for that), Mercurial's branches are too permanent in that they cannot even be renamed (well, there's an extension for that, but that's not without issues). Mercurial bookmarks still do not allow you to label sets of commits, but at least aren't responsible for the liveness of a commit.
In practice, I like both Fossil's and Bazaar's model better.
What do you mean by a "set of commits". Why not just have topic branches?
Branches isn't the only thing that keeps commits alive, you also got the reflog and tags. I have a hard time understanding why you would want to keep something alive that isn't reachable from the history.
Branches as sets of commits are useful for understanding history. I.e., which commits conceptually belong together and with a quick descriptor of what their purpose and/or who their primary author is (or whatever else your chosen policy for naming them is).
That branches are not the only refs that keep commits alive is irrelevant, because the other refs by themselves are not sufficient; not every commit is reachable from a tag and reflog entries expire. Branches remain a necessary ingredient.
Git needs this because it requires a named head for each commit because (1) it has a garbage collector and (2) it doesn't allow for multiple checkouts. In version control systems with multiple checkouts, a new branch will typically end up in a checkout of its own. Because there's no GC, it will not spontaneously disappear, and because each checkout keeps track of its own head, there's no need to name it. Git branches are an artifact of Git's odd architectural choices.
But my bigger point is not about wanting to keep something alive that isn't part of the history, but that branches may not always accurately reflect what's part of the history (because Git allows you to alter them, and that's often even part of the normal workflow, e.g. deleting a temporary branch once you don't need it anymore). This usually does reflect human error, but, well, a major point of using a VCS is to protect against the results of human error. If you messed up your branches, then you can lose data either because (1) it eventually gets garbage-collected [1] or (2) it doesn't get pushed anymore and some day your computer or hard drive breaks. This is what I meant by Git introducing fragility.
[1] Yes, once the grace period expires and it disappears from the reflog, but that only makes it less likely, not impossible, especially for stuff that sees only intermittent work.
Well, you can set the expiration period for the reflog. If I remember correctly you can set it to "never". You can also disable alteration and removal of branches on a remote git repo. It's really all about knowing your tools.
Then again, in my experience, if you manage to remove data or alter data which should not be removed or altered, and don't pick up on that before after the reflog expiration period, then you have bigger problems.
> Well, you can set the expiration period for the reflog
Much easier, you can turn off garbage collection (if you set the expiration time on the reflog, you have to make sure to set gc.reflogexpireunreachable, not just gc.reflogexpire). This is indeed what I do whenever I work with Git as the frontend (though not when I uses Git programmatically as basically a versioned DB backend). But that's not about me. I'm fully conversant in Git, up to and including having hacked Git repositories using dulwich. It's about users in general, all of whom have to deal with this.
Of course, this has its own problems, because lots of Git usage patterns have evolved around creating garbage and then throwing it away rather than having an explicit and safe delete operation that is rarely used (or at least to hide revisions rather than to delete them), and because it may not be possible on hosted repositories, such as on GitHub (Bitbucket allows you to prevent force pushes to master branches, GitHub doesn't [1]).
And even when you've made it safe, you still cannot have unnamed branches or multiple checkouts [2].
The more general problem is that Git's GC is not a user interface design decision. Git having a GC is ultimately a result of it being easier to hack together your own transactions without using an actual DB backend such as SQLite when you use (mostly) functional data structures with a GC. While this makes Git a fairly robust versioned database, these and other implementation decisions spilling over into user space is something that has plagued Git for a long time: for full proficiency with Git you need a fairly deep understanding of implementation details.
> Then again, in my experience, if you manage to remove data or alter data which should not be removed or altered, and don't pick up on that before after the reflog expiration period, then you have bigger problems.
This can easily happen on branches that see only intermittent changes or on personal repositories. Git was originally designed for being heavily distributed work, and it shows; it's relatively safe when commits are regularly mirrored to a network of contributors, not so much when they don't.
And, again, this is a problem that should not even exist. One of the primary tenets of source control management -- a major reason why we even have it -- is to protect developers against their mistakes. In particular, there are many cases where VCSs are being used by non-technical people (such as technical writers working on documentation) and they cannot be expected to have a deep technical understanding of the tools they are using. VCS tools must therefore be error-resistant.
[1] GitHub in many ways is still shockingly primitive, such as how it still doesn't support attaching files to issues. Referencing gists via URL is a sort-of workaround, but even that becomes painful with binary files. But that's another story.
[2] The reason for the latter is subtle, but basically boils down that the GC either needs to have global knowledge of all checkouts in order to trace checkout-local refs such as HEAD properly (which may be lost by a simple mv) or that multiple checkouts that use the same branch can get in a battle over who gets to point it to which commit (e.g., commit to master in two checkouts, and only one commit operation can "win", because master cannot point to two commits at once).
> ... lots of Git usage patterns have evolved around creating garbage and then throwing it away rather than having an explicit and safe delete operation that is rarely used
Any delete operation in Git is safe. At least compared to delete operations in other vcs's (hg strip comes to mind).
> may not be possible on hosted repositories
That isn't Git's fault though, but the hosted repository. You could say the same about Mercurial bookmarks.
> And even when you've made it safe, you still cannot have unnamed branches or multiple checkouts.
I don't understand why this would be nice to have. Mercurial had the former, which to me was completely useless. Should I ever want to go back to a previous unnamed branch, I would have to actively search for it, which on a large project would take forever. I always keep my branches named, after the issue number, for this particular reason.
I don't really understand what multiple checkouts are for (a quick google gave me nothing). I would assume it would be something like having multiple local repositories, but I assume that is not what you're getting at?
> a fairly deep understanding of implementation details
Which takes literally fifteen minutes to teach (at least the way I did it), and after that it becomes a lot easier to explain what the different commands actually do.
> it's relatively safe when commits are regularly mirrored to a network of contributors, not so much when they don't.
A network doesn't provide any more safety (except from a computer crash), as you don't push garbage.
> is to protect developers against their mistakes
To a point. To be completely safe we would have to auto-commit on fixed intervals, like a traditional backup system. Instead, the user is empowered with the decision to decide what gets stored. If the user wants to remove something entirely, or re-write history to make it more readable or whatever, he/she should have that power too. A default 30 days of full history is, IMHO, quite reasonable given what the user can do. If that doesn't meet your requirements, then there are other, better options out there.
> they cannot be expected to have a deep technical understanding of the tools they are using
They don't need one. Have someone teach them git add, commit, push, pull and merge. Then teach them to NEVER rebase. Done.
We could probably go back on forth on this a lot, as we're unlikely to change each other's position, I'll call it quits. Thanks for a fruitful discussion :)
> Any delete operation in Git is safe. At least compared to delete operations in other vcs's (hg strip comes to mind).
While I'm not a big fan of Mercurial's strip implementation (because the management of strip backups is cumbersome), in order to permanently lose data there you'd have to do hg strip and then also expressly delete the backup in a separate step. Git does the deletion on its own.
More importantly, you seem to be mistaking this for a Git vs. Mercurial argument. I am not making a Git vs. Mercurial argument; if anything, my position is that "Mercurial is less bad than Git, except in some areas where Git is less bad." And even that's not what I'm getting at, because I'm not interesting in comparing them against one or the other, but to point out that both are lacking.
In general, SCM development has stalled since the late aughts and content with a relatively subpar state of affairs. That too many people seem to think that Git and Mercurial are the only DVCSs ever invented and that centralized version control means either CVS or SVN doesn't help, either. My interest is in getting less primitive version control than the existing systems, not defending the antiquated status quo (antiquated to the point that there are even older, now forgotten systems that did some things better than the current crop).
> That isn't Git's fault though, but the hosted repository. You could say the same about Mercurial bookmarks.
Mercurial bookmarks, if misplaced, do not result in revisions on a server becoming inaccessible.
About unnamed branches:
> I don't understand why this would be nice to have. Mercurial had the former, which to me was completely useless.
They go hand-in-hand with having multiple checkouts. Create a temporary branch in a second checkout, and you don't need any label for it (because it's the tip of that checkout).
> I don't really understand what multiple checkouts are for (a quick google gave me nothing). I would assume it would be something like having multiple local repositories, but I assume that is not what you're getting at?
For example what (as I noted) git-new-workdir attempts to do (again, that's unsafe, use at your own risk). If you aren't familiar with this concept, you can't know very many VCSs, though. It's supported by all DVCSes other than Git in some form of another (though arguably a bit indirectly in Darcs, and Mercurial's version doesn't have good commandline support). It is also obviously supported by all centralized VCSs.
It simply means that you can have two or more checkouts (working trees, in Git parlance) of the same or different revisions, but only one shared repository. Multiple clones can only crudely approximate the behavior, since you can't directly diff or merge between branches in different clones, say. A simple example of the usefulness is to be able to compare the behavior of different versions side-by-side (particularly when you're dealing with slow builds). Another is to be able to create a separate checkout for an urgent bugfix without interrupting your current work, then easily integrating that bugfix into your work.
> A network doesn't provide any more safety (except from a computer crash), as you don't push garbage.
My point is that the likelihood is higher that accidentally deleted material has already been shared with other developers, so it's more likely to be recoverable if you misplace a branch.
> To a point. To be completely safe we would have to auto-commit on fixed intervals, like a traditional backup system. Instead, the user is empowered with the decision to decide what gets stored.
Agreed. But my point is that Git unnecessarily trades away security, based on an implementation decision (to achieve transactional properties by using functional data structures plus garbage collection). Nothing is ever going to be perfectly safe, but that was entirely avoidable.
> We could probably go back on forth on this a lot, as we're unlikely to change each other's position, I'll call it quits.
I don't ever expect to change anybody's opinion; I am merely explaining.
The reason I use Mercurial as an example is because that's the other DCVS I'm most familiar with.
> A simple example of the usefulness is to be able to compare the behavior of different versions side-by-side (particularly when you're dealing with slow builds).
That usecase I can understand. The other two you mention though could easily be solved by branches.
Not related to the core product but still very important for the experience: A decent Windows gui, tortiose hg. I have tried all the guis for git, both commercial and free, and they all suck rats ass. Either they are slow, they only support github, they look like shit, they only support the most basic commit operations, they can't show the diff between selected revisions, they destroy your merges and simply make everything related to source control a pita. There are many many of them available that can do some of the things I listed above but none that does all of it.
Mercurial was a real eye-opener. Before a friend basically made me try Mercurial, I was using Subversion for managing my private projects, and it was not exactly fun. Especially when I was working on my laptop (netbook, actually, but that is totally OT), away from home, without access to the server.
Mercurial made VCS fun. I recently moved on to Fossil, because I do like the integrated wiki and ticket system for smallish projects, but without Mercurial I never would have gotten there.
I also like Mercurial's hooks. I am not sure if other DCVS support that, but hooks are great. (Fossil doesn't appear to have them)
I'm excited to see improved mercurial support at bitbucket in the near future. While bitbucket's support for mercurial goes back many years, mercurial itself has evolved a lot in the meantime, and bitbucket has been focusing more on support for git for several years now. At the very least, I'm glad they have someone on staff who cares about mercurial so new features don't break things for mercurial users.
> The future of Mercurial is that of scalability and because of that, I believe the best days of Mercurial are ahead.
That sounded to me like Mercurial has started to carve their own niche after losing the popularity war to git (maybe just my wishful thinking?), and this may have very good outcomes since currently all scalable mainstream vcs choices are centralized.
Git developers showed they're hardly interested in this area, and Mercurial have had some head start with the contributions from Facebook. I don't think anybody would object it if we had a free dvcs that can respond to very high scalability needs without hacking around its deficiencies. This is the point where Mercurial project should reconsider its priorities and even put some of their current priorities into back seat if that's what it gets to achieve their new goals with no compromises.
I love all the new things the mercurial developers are willing to experiment with and try out. It seems the (sometimes maligned) plugin system that mercurial uses makes this easy. It's been really interesting to see how our (mercurial developers' and users') ideas about how distributed version control can and should be used have morphed and changed over the years. I remember when mercurial's branching recommendation was to have a clone per branch and when we all hated the idea of modifying our history. Now mercurial supports 4 different branching models and has excellent history editing support with commit --amend, rebase, histedit, and changeset evolution. I'm excited to play with the other new features that are coming.
> These include the concept of changeset evolution coming to life and the announcement of both Facebook and Google choosing Mercurial over Git.
Perhaps this is true for Facebook. But I can say that Google most certainly does not use Hg over Git. The Go source code used to be under Hg, but they've recently migrated to git.
Creating a throwaway for this because I don't want to get anyone in trouble.
Today, right now, neither Facebook nor Google are fully centralized on Mercurial. Facebook uses a mixture of Subversion of Git, and Google uses a mixture of a system that is totally not Perforce why do you ask please do not look behind the curtain, and Git.
Moving forward, this statement will be true for both companies. In Facebook's case, they are narrowly focused on truly moving everything into Mercurial, and are heavily using Mercurial's extensibility to facilitate that. remotefilelog (https://bitbucket.org/facebook/remotefilelog) is a key part of this, but they've been doing lots of other stuff that's not public that I can't link to that lets them get further. This process is well underway, but (last I heard anything) is incomplete.
Google is going a different direction, because Google. They're aiming to extend out their not-Perforce system to speak scalable Mercurial protocols. Given that they have experience storing Mercurial and Git inside Subversion repositories on top of Bigtable, this actually strikes me as a relatively sane engineering decision, from their perspective. This project is not ready for use. Even when it is, public Google projects will continue living on GitHub, which means that Go will continue being Git for the foreseeable future (as will FOAM, Blaze, and anything else they want contributions on).
For smaller projects (up to the size of the Linux Kernal) it seems Git and Mercurial are pretty interchangeable so people go with Git and GitHub due to network effects.
Also, just because they're using git for public projects doesn't rule out that they may be using mercurial internally. Google pays a number of people to work on mercurial... I'm not sure if that's the same for git.
If you look at development at Google, you'll see most people on a perforce derived repo system , then groups like Android, chrome, Etc on git, then basically very few teams using Mercurial.
We do have some hg contributors like augie, but we have way more git contributors, includes git project Lead Junio.
I'm very excited about bitbucket improving their hg support. The blog poster, Sean Farley, was previously working on Kallithea before going to work at Bitbucket. I met him during Pycon. From my understanding, he's still allowed to work on Kallithea.
I'm excited about Mercurial's future. There are so many great things coming out. New ways to handle branching, shallow and narrow clones, an experimental interface for running hg over a git store...
> an experimental interface for running hg over a git store
It would make me very happy to be able to interact with Git repos through an interface that didn't make me want to kill myself with a rusty railroad spike.
I gather the difference is that hg-git has a mercurial repo locally and maps hg bookmarks to git branches and commits at push/pull time, while it seems like this experimental interface is using the HG UI against a git repo locally, but why is this better?
hg-git converts git repos into hg repos, while hgit lets you do `hg commit` or `git commit` on the exact same git repo, with the exact same hashes.
Why is it better? Converting a git repo to hg takes a long time, you need a way to translate hashes back and forth between the two repos, bookmarks in hg are not exactly the same as branches in git. Or in the words of Cervantes, "translation from one language into another [...] is like gazing at a Flemish tapestry with the wrong side out."
I started with and loved Mercurial as a DVCS, and it still has some QoL commands that Git requires some hoop-jumping to get at, but ultimately the deciding factor was the inability to permanently delete branches. Since branched dev work would fairly regularly have generic names or the names of the developer working on it, it would always end up being forked and merged instead of branched and merged, which led to a ridiculous number of headaches in our build system.
We still use mercurial for most of our repositories just because they're dated and not likely to see more than a handful of commits a year, but most of our active development work has already converted to git.
Well, IMHO, nowadays this classifies as bad design. It may have been the better design, but currently git's nomenclature is the standard and not complying to it will only hurt mercurial.
Mercurial and git were initially released within a couple of weeks of each other. To change terminology now would break ten years of backward compatibility.
I used bookmarks back when I used Hg, which is a couple of years ago, but I had some problems with them. From time to time bookmarks wouldn't update remotely. This made me always push twice, to make sure the bookmark was updated. They've hopefully fixed that now, but it was one of my main gripes with Hg. That, and that the Jira version we switched to didn't support bookmarks.
Not sure what the difference between "forked and merged" and "branched and merged" is. You can use rebase/histedit to delete branches in mercurial if you want to.
So, you would prefer one big release every year with hundreds of changes?
I will take small, incremental improvements over massive upgrades always. If something goes wrong in a monthly release, the change log is short enough for me to read every item and probably figure it out in a few minutes.
I cannot think of any benefit to a slow release cycle with large changes bunched up into versions, and consider it a major negative when I am choosing software (I'm currently upgrading to Drupal 7 from 6 and its been almost funny how much of a disaster it's been).
There's a reason Chrome and Firefox and Manny others do rapid rolling releases. It simply delivers better software faster and with less likelihood of catastrophic problems. Small changesets are just easier to fit into a human mind.
Mercurial user for the past 6 or 7 years here. I cling to Mercurial despite people asking me to move some of my side projects (nothing substantial though) to git and github.
I refuse to do that out of principle. I think Mercurial should have taken the place of git as the widely used DVCS. And I try to be THAT change I want to see.
That being said, It would be great if someone can get the hg-git plugin to work seamlessly with newer versions of Mercurial on Windows and Linux, so that I can keep using Mercurial even if a project I am involved in uses git.
I was really surprised that Git "won" because I thought that Mercurial's friendlier CLI and being written in Python would give it an advantage. I think I underestimated how good it makes people feel to understand something incredibly complicated. I guess immutable history was a turn off for many people as well.
This fake interview is pretty funny:
"Linus: Git has taken over where Linux left off separating the geeks into know-nothings and know-it-alls. I didn’t really expect anyone to use it because it’s so hard to use, but that turns out to be its big appeal. No technology can ever be too arcane or complicated for the black t-shirt crowd."
That is a clever fake interview quote, but the whole notion that hg's "easier" interface should have made it won misses the point. hg's interface is more familiar (especially since we were mostly all coming from subversion at the time). Git won because it's workflow is so much better than mercurial's. Light-weight branches are better than hg branches (I know they have bookmarks now but I don't recall if they had them back then). The index is a fantastic idea that makes writing clean commits easy (I think the comparable hg option at the time was mercurial queues which are much more cumbersome to work with imo). Rebase is functionality that hg didn't include out of the box. Being able to edit commits in git is something I greatly appreciate for fixing typos and stuff.
tl;dr: the interface of mercurial may be more straightforward, but git won because it allowed people to work better.
You're right that Mercurial didn't have bookmarks until years after Git had branches. There were various things you could do to get a similar effect (eg having a branch with multiple heads), but none quite as good, and it took the Mercurial team a long time to come around to the idea.
I have to disagree about the index, though. I use Git every day, and i'm still struck by how pointless the index and the idea of staging is.
Ditto rebase. The routine use of rebase still seems completely wrongheaded to me. Mercurial's convention of preferring merges is better, and the last few years' developments around safe evolution of history really show rebase up as the misconceived hack it is.
Mercurial got 'commit --amend' a long time ago, but even before that, it had 'rollback', which undoes the last commit, leaving the working tree untouched (that is, with the state it had in the commit), so you can make your fixes and commit again.
I'd entertain the argument that Git won because it was better if even a handful of the people who now use Git had learned both Git and Mercurial and made an informed choice between them. That simply does not appear to be the case. Git got ahead because Linus invented it, and won because of GitHub.
I use Git every day, and i'm still struck by how pointless the index and the idea of staging is.
I find it amazingly useful. The staging area is for building your commit. I always ever use -p (ie., "add -p", "reset -p" and "checkout -p") and use it to construct the commit out of parts.
The way I work, I split my current work into multiple commits. I may have implemented a feature, fixed a bug I found along the way in the same file, and updated the readme with something unrelated; those are three separate commits. I do "add -p" to pick the fragments, and when I'm happy, I commit. Repeat until repo is clean.
Sometimes, my current work results in a whole bunch of such commits. Sometimes I have to split part of my current work into a separate branch. Again: Stage stuff, stash -k, checkout new branch, commit as a WIP commit, go back, unstash.
Darcs has "record", which is like "add -p" except it also commits at the same time, and back when I was using it, I remember hating the fact that it required that everything had to be recorded in one go. Git's incremental staging area is much more pleasant because you don't get stressed out by the impending commit that is looming over you.
I prefer to use shelving / stashing to do this sort of stuff. This way you don't need to learn two ways to do the same thing and you can be sure that the code version that you commit is the same that you ran your tests on.
In contrast, I never use `git stash`. Never-ever-ever-(ok-rarely). It bit me HARD early on, so I prefer to do it manually, or rebase branches.
One thing I really like about git is that it lets me be mindful of my actions in a way that hg didn't seem to encourage. In return, it gives me what feels like True Power to recover from _any_ mistake. Wrong branch? Accidentally merged (and pushed) my master branch? No problem, they're just bookmarks to commits anyways.
Mercurial, by contrast, felt Rather Convenient, with occasional chasms of despair if you strayed too far from the path. It's possible that my high opinion of Git is mainly from the fact that it forced me to learn more, but it really feels more flexible. I always have the right tool for whatever I need, and I know why and how to use them.
I use Git on a daily basis, but I never understood it.
If I just want to commit a specific part of my changes, I just do it. It's nice to see which files are staged for a commit, but I also see them in the commit msg comments.
They're called "hunks" in git parlance: sections of the file that define a "diff". A diff on a file can be made of multiple hunks.
Very often, my changes to a file are a mix of "fixing a serious bug" and "minor refactoring" and "removing dead code". When the time to commit comes, git makes it trivial to separate all these changes in different commits so that each commit does one thing and one thing only.
I just noticed recently that TortoiseHG lets you do that in the GUI. Definitely is a nice feature. I only just started using Git and did like the ability to cherry pick from a file, but happy to know I can still do that with hg.
Actually Hg record can do this. It lets you 'edit' a hunk using a text editor, before adding it to the list of changes to include in the current commit....
> if even a handful of the people who now use Git had learned both Git and Mercurial and made an informed choice between them. That simply does not appear to be the case. Git got ahead because Linus invented it, and won because of GitHub.
I think you also underestimate the developer community (or may I overestimate them.) Regardless, my anecdotal evidence is that I did try HG and Git, and while I preferred HG when I first started evaluating them, as soon as I found out how to use Git branches, it was all over for HG. At work we currently inherited a project in HG and everyone that has to work on it complains about it. Some know Git, some are .Net or even old school CVS/SVN people (our VCS migration took a bit longer than it should have), but it doesn't matter. HG = hard to use for them, whereas Git make sense after getting over the initial hurdles. I see the same kind of path I took, where at first they are like, oh, Hg isn't bad, and then after using both, choosing Git as their preference.
I used Mercurial for years because I tried early git and didn't like it. Then I tried it again, everything was easier than Mercurial and I wouldn't ever go back.
Hey, if you don't use the index then don't use the index. Use git commit -a. If you wan't something like the index in Mercurial you have to specify which files you want to commit, or which to exclude, which IMHO is a lot more tedious and error prone. Then again I haven't used Hg in a couple of years, could be they have something like the index now.
Rebase is a hack? Rebase copies a series of commits on top of an immutable history at a certain point in time. This allows you to deal with merges a single conflict at a time, instead of dealing with all the conflicts at once with a merge. It also allows you to avoid cluttering your history with useless merge-commits when just syncing with another repo.
Merges have their place. I use them whenever I merge branches, using --no-ff so I can attach a "Fixes issue #77" in the merge commit message. Of course, before I do that, I sync the branch I'm merging into, then rebase on top of that (to have a clean merge). I might also rebase --interactive to clean up the commits of my branch, so that the history is as easy to read as possible.
Comparing rebase to rollback is wrong. Git has rollback (or revert) as well, and it's used for other usecases, like when reverting changes on a public branch (where rebase would fuck it up for everyone).
I'm sorry, but your comments make it sound like you don't really understand Git.
>Rebase allows you to deal with merges a single conflict at a time, instead of dealing with all the conflicts at once with a merge...
Not sure what you mean by 'deal with a single conflict at a time'. To rebase or merge, you will have to resolve all conflicts that merge/rebase produce, right?
Yes, but a rebase re-applies every commit to the new base. So you solve conflicts one commit at a time, instead of solving every conflict in a single merge commit.
It's easier to remember the intended behaviour when the code changes are as small as possible, and when you have a (hopefully) good commit message to look at.
I am not sure it make any difference to the user at all. If you use a merge tool, it will present the conflicts one at a time for merging and re-basing.
If you are concerned about reading history, then a merge can give you more context regarding the commits. With re base, commits will jump between features. For example, You are looking at commit for feature 1, but the next series of commits are for a bug fix in feature 2. Next series of commits belong to minor tweaks in feature 3..
A merge will provide you with a single commit-message, rebasing will provide you a commit-message for every commit, making it easier to remember what the intent of a change was. Sometimes that isn't clear.
Regarding the "rebase, commits will jump between features" part: that really depends on how you do things. On my projects, we use git flow. In such a scheme, every branch you would rebase, belongs to the same feature or bugfix.
>In such a scheme, every branch you would rebase, belongs to the same feature or bugfix..
Not sure if I made that clear. But I was talking about the result of the rebase. Once you rebase, all the commits that were in different branch ends up being back to back, and hence become interleaved...
I don't use hg much these days but you can just pass the file(s) you want to commit to 'hg commit'; no need for staging. Even better, hg (or its shell integration at any rate) has tab completion so it's easy to go though the modified files and pick those you wanted to commit. I kinda miss this now I'm working with git mostly.
>Git won because it's workflow is so much better than mercurial's.
This is quite subjective. A more probable reason is that git is popular because of github..
And once git gained some popularity, people started viewing other DVCS as inferior because they were doing things differently from Git. For eg, the branching in Mercurial. People are appalled when they see how named branches can be done in Mercurial. Without going into any thought or reflection on how Mercurial's named branching can be useful in certain situations, they call it braindead. But actually git's branching is quite simple and less powerful than the methods offered by Mercurial. Less powerful, because Mercurial offers multiple methods to make a branch so that you can use the right one for a particular situtation. Note that this actually asks for more experience from the user. He needs to have experience with using each of these methods and should know how each of them may be useful in the future. It also stores more metadata and tools like revset which lets you to build powerful queries. So in that sense, Mercurial is also more complex than Git. But that is in a good way and unlike git's, it is not the complexity that gets in your way.
So in short, I think git is actually quite simple than Mercurial, but hides that simplicity behind a complex interface with non-intuitive naming and weird combination of flags and stuff. This causes the 'Aha' moments when one can finally see the simplicity that hides behind that interface, which trigger a huge release of Dopamine and prompts the user to write his own set of Git revelations that (used to) flood the internet, which in turn increases the popularity of Git...
The main thing I found was that Mercurial was only easier for the simplest introductory tasks, where Git has largely compensated with tons of documentation, tutorials and, later, improved command-line UI. Once you needed to do anything more complicated (e.g. working on against an upstream repo you don't have commit access to) you tended to quickly end up in documentation lacunae and semi-supported extensions which rotated in and out of favor depending on which year the guide you'd found was written.
My team started using Mercurial a couple years before Git but eventually migrated over because in practice Git was less surprising and nobody had lost data using it.
"I underestimated how good it makes people feel to understand something incredibly complicated"
Or rather (in many cases) how good it makes people feel to use and tell other people they use something incredibly complicated, whether they actually understand it or not.
I'd venture that a fairly large amount of the people who use git don't really understand it fully, they just understand some very small subset of what they picked up from whatever "best git flow" website or book they happened to read.
Lest anyone think I'm being elitist here, I'll come right out and admit there's a ton of stuff in git I've never bothered to really understand. I'm okay with standard push/pull commits, stashing and rebasing, but I still kinda think of these things as sort of interpretations of concepts I'm used to from older non-DVCS systems, I don't "grok" git, not really -- never really bothered since I find source control systems incredibly useful but not inherently interesting (to me personally).
All that said, I don't use git to show off, I use it because virtually everyone else does and there is a certain pragmatic benefit to going with the flow on something like that even if I think it is overkill for a lot of the projects I need a VCS for.
This attitude of "oh, the only reason it's popular is because people want to feel superior for learning something hard" is poisonous to productive discussion. If you're going to be cynical about it, at least favor the "OMG Linus Torvalds maed it" explanation over the one that requires active assholery on the part of Git users. Better yet, try assuming that most people are making a reasonable effort to be rational based on their limited knowledge. But what you did right there, please don't do that.
Anecdotal of course, but in my limited experience, I've seen plenty of superiority complexes and generally assholery, but no Linus fanboyism. I don't like it, but to me it seems like a perfectly unsurprising aspect of the software industry.
Your idea (my interpretation) that the industry mostly consists of people having productive discussions seems more off base. Yes, that's the way it should be, and usually is on HN and similar forums, but out in the larger real world, arrogance, superiority, etc are the order of the day.
Yes, I know the real world sucks. In light of that, let's try not to actively make it worse. Applying Hanlon's Razor aggressively is the easiest thing we can do. And don't forget the selection bias from the fact that jerks are more likely to make themselves noticed than rational people.
Or you could mention the elephant in the room, the fact that git is orders of magnitude faster than mercurial when your project grows beyond the "small" size. Mercurial would be unusable on something like the Linux kernel, and uncomfortably slow on a lot of other projects. And big projects tend to have more developer mindshare-- funny how that works...
Except there are large projects using Mercurial without issue. See Facebook for example. If you want to look at open source projects, all of Mozilla uses mercurial[0] with just the standard hg-web server. And it's size is comparable (same order of magnitude) as the linux kernel)[1].
If you want to make such claims, I'd love to see data backing it up.
It was performance that made git win initially. In benchmarks git did better in the past when there was still a great Cambrian explosion of DVCSs (Monotone, Bazaar, Hg, Git, Darcs,...)
It is of course possible that performance follows a saddle like curve (or hump depending on how you look at it). For up to some size, git is faster. But at much larger ones a different algorithm wins out and hg could be end up being faster.
The friendliness in the mercurial CLI ceased to be an advantage just a few years after git came out, IMHO. git error messages got better. I had to re-use mercurial after leaving it for git at one workplace, and I was cringing most of the time.
The main problem is that mercurial never got real branches, which is git's wheelhouse, forcing gross things like the "forest" extension (which I believe is now unmaintained). Maybe it's gotten better since then, but this was about 3-4 years ago.
The way I see it, git has all the powertools you'd need, and you don't have to use them most of the time, where as mercurial feels generally stripped down to be "easy", and when you want to do the hard things, it's not so good at it.
One of those examples might be something like grafting a repo into another repo at a arbitrary root, or some of the tricks you can do to edit previous commits (say if you mispelled your username all the way down).
My main point of switching originally was when I believe it mixed up a lot of commits in a merge and lost some changes. I also recall hearing about a patch for predictable ordering in diff output being rejected.
git's really gotten TONS better -- way back, I would say mercurial was easier to use, and git really excels at branch based workflows which at this point I can't live without.
Of course, a worse thing from having to work at a mercurial shop after loving git is having to work at a SVN shop :)
> I was really surprised that Git "won" because I thought that Mercurial's friendlier CLI and being written in Python would give it an advantage.
What we've learned is that these two things are actually liabilities.
git is a good example that the syntax of the command line is of no consequence. git's CLI is notoriously horrendous and bizarre, yet it didn't stop its adoption. And this is a problem that's easily worked around by creating tools (graphical ones and also porcelaines) around it.
The fact that Mercurial is written in Python has a big impact on its performance, and git is running rings around it as a result. When you run tens of commands every day, it adds up.
Strangely enough even git's initial hostility to running on Windows didn't stop its adoption.
git's features and modeling of source control system is so powerful and flexible that git became successful in spite of all these other aspects.
Frankly, I think it's silly to use any other source control these days: embrace git and get used to it because it's going to be around for a while.
> The fact that Mercurial is written in Python has a big impact on its performance, and git is running rings around it as a result. When you run tens of commands every day, it adds up.
This wasn't the case at all. In their early years, some operations were faster on git, and others, faster on Mercurial[1]. I don't remember any recent benchmarks, but early last year, there were reports of Facebook making Mercurial faster [2].
> Frankly, I think it's silly to use any other source control these days
You might get that impression if your work is centered around github, but I have friends who use enterprise-specific extensions on Mercurial that structure their workflow.
You're not really disputing what I said: Mercurial is much, much slower than Git. Facebook forked it and managed to make it faster but they never released their fork so nobody can actually use it.
The bottom line is that a program written in C will always be orders of magnitude faster than a program written in Python. This is not news.
> You're not really disputing what I said: Mercurial is much, much slower than Git.
Yes, I am. And I gave a reference for it.
> Facebook forked it and managed to make it faster but they never released their fork so nobody can actually use it.
I invite you to look up the license that Mercurial is released under. And then I advise you read [3]. And why do you keep making these unsubstantiated claims?
> The bottom line is that a program written in C will always be orders of magnitude faster than a program written in Python. This is not news.
If we're comparing exactly the same algorithms implemented in both Python and C, C would usually be faster. But we are not discussing the implementation of simple algorithms. We are talking about complex software, with different architectures.
"The fact that Mercurial is written in Python has a big impact on its performance, and git is running rings around it as a result. When you run tens of commands every day, it adds up."
Totally agree. Mercurial really is the product that deserves the spot that Git has claimed in terms of being the defacto DVCS. It's generally easier to use, well supported, and more intuitive. The good thing is that there is still a healthy competition out there to push ease of use and features forward. I think promoting Mercurial to help it gain market share is important. You don't have to suffer through Git!
What a silly comment. If using git is suffering to you, then don't. You know what? I hate peas. You know what else? I don't eat them.
You know why git won? HG was slow as molasses when they both showed up on the scene. That and git's branches are a dream come true. I think back then, an HG branch was a clone of the repo.
I can't figure out what sort of suffering people are talking about.
Same story here. I learned both Git and HG circa 2007 and decided HG had a more pure DVCS model. I still believe that's the case and still use HG. When I interact with GitHub I use hg-git. Long time Git users: I strongly encourage you to try Mercurial.
Every time I try HG, I find that to do what I want I have to get a bunch of plugins. When I use a VCS, I want to know that I'm using the same commands as everyone else, so that we are all speaking the same language.
Most of the git commands I use are about as straight forward and simple as they could be. If ever I manage to screw something up, the archeology commands I end up using are obtuse, but it's rare that I need them. And I'm glad they are there when I do.
Are they plugins that you just enable in the conf file? If so, all extensions that ship with mercurial are fully supported features. They just disable parts of the cli that can be dangerous or are less commonly used.
If you are having to download 3rd party extensions, then that's a different problem.
I've learned git first and found Mercurial hard to use.
I've somehow created a branch that couldn't be deleted. Instead of being really deleted it appeared in remote repository as some kind of a "tombstone".
I've tried to rebase, but to do that I had to fiddle with settings and enable plugins.
My impression was that Mercurial is a higher-level version of git, with the sugary layer doing things that I don't want.
> I've somehow created a branch that couldn't be deleted.
The problem here is one of conflicting terminology. What Git calls a branch, no other version control system calls a branch. A branch in Git is really a moving pointer to the head of a branch as other VCSs would see it.
The confusion can go both ways, by the way. I.e. when a user who is used to another VCS expects a branch to be a persistent label for a set of commits and then discovers that it doesn't work like that for Git repositories and that your branches may "move" or "disappear" and don't even describe sets of commits but individual commits.
SVN tags and branches correspond quite closely to Git tags and branches, I think; "tag" is a naming of a commit, "branch" is an evolving repository that shares history (and perhaps future, if merged) with other such "branches".
Except Git tracks history of the named branch in the reflog, and SVN (and others, I would guess) track it inside the repository. This is a huge difference for archeologists, but quite minor in practice from my experience.
Git doesn't really have a technical difference between a tag and a branch either. They are both files containing a hash for some commit. Tags are just more cumbersome to move (branches are moved on new commits), and they can be signed cryptologically(is that a word?).
Similar story here. I had been using hg almost exclusively for the past 5 years, not just for personal side projects but also at work with teams using git, thanks to hg-git. Admittedly hg-git had/has its issues, especially slower push/pull performance compared to both standalone hg and git, and occasional friction with the rest team that was using git exclusively. I tried to grok git during this time and gave up more than once out of frustration.
Eventually, just less than a year ago, I bit the bullet and made the switch to git. What did the trick for me was a list of short aliases I copied from somewhere, tweaked and have been maintaining in my ~/.bash_aliases ever since. Some aliases are just shortcuts for super common commands (such as "alias gts='git status'") but others remove the burden of remembering what combination of commands and arguments make sense to me ("do i undo a change with revert, reset, checkout or something else? well it depends.."). I still can't claim I know git in depth but it's good enough for day to day usage.
I find Mercurial easier to use, even though I use git much more. I also find it harder to shoot myself in the foot with Mercurial - I've destroyed (but not lost) work with git quite a few times.
Mecurial is super easy to learn - there is no reason not to be comfortable with both.
> I've shot myself in the foot a few times with git, however, git reflog is _often_ there to help.
Many times this. Git reflog is an extremely powerful feature to fix mistakes. Any git user should at least in base understand what the reflog is and how it can be used for roll-backs.
I don't know what the wins of hg are. Used it for a year
Git has git style branches which make it really easy to work on different things. Apparently hg added some of that later but it's not the main workflow
git also has a "staging area". You put things into the staging area and then commit. So for example the equivalent of "hg commit" in git is "git commit -a". The -a means "copy everything that's changed to the staging area".
The advantage of the staging area is it's easy to commit just a few files even if many have changed. It's even easy to commit just a few changed lines from a file and leave the other lines un-commmited.
There are other advantages I'm sure and I'm sure I didn't explain the branching one well. I can point out that I have repos with completely unrelated branches. One branch is the website, another branch is the docs, another branch is the source code, branches in hg, at least the default ones, are assumed to be something that will eventually be merged back. hg complains forever until you merge the branch back. git branches are effectively unrelated to each other, although by default git will track where it branched and if you happen to merge them where they merged. branches can be pushed and pulled to other repos or not, it's up to you.
Someone above said hg has bookmarks that are similar to git branches but I'd be curious if they're actually the same.
Interesting. I started in hg for a year then switched to git. It took a while to get used to but once I did I never wanted to go back to hg.
I've heard hg since then has added features that make it possible to have a more git like workflow but AFAICT it's still not the "recommended" at least not the default workflow which means I have no desire to switch back.
"In my time with Mercurial, I have seen it grow in fascinating ways. These include the concept of changeset evolution coming to life and the announcement of both Facebook and Google choosing Mercurial over Git. The future of Mercurial is that of scalability and because of that, I believe the best days of Mercurial are ahead."
Is it time to give Mercurial another shot? I first migrated from SVN to Mercurial way back when - but after the massive increase in Git's popularity I bit the bullet and switched.
What does Mercurial have over Git today?