Early-stage Git/Mercurial/Bazaar evaluation thoughts

A few weeks ago I decided to start seriously investigating switching to a DVCS. I’m currently up to my eyes in work and haven’t really had time to progress that in the last few weeks; however some absolutely abhorrent performance / reliability problems with Sourceforge’s Subversion server made a large merge process so costly to me (in the end I had to commit in small chunks, breaking transactional consistency, and it needed so much babysitting because of the speed / reliability it took me 4 bloody hours just to commit!!) that it bumped it up my agenda a bit. I don’t have to do merges / commits of that size very often – in this case the problem was wholesale license header changes for our MIT switch – but still, it’s totally unacceptable to have to deal with that. I raised a support request with Sourceforge, but I’ve seen other reports of bad SVN performance from several weeks ago from others, so I’m not holding my breath. It’s time to start considering alternative hosting I think.

I’m not done with my evaluation yet, because I just don’t have the dedicated time I really want to spend on this right now. But, here’s my early-stage results.

Git

I’ve discussed before that I don’t like the where Git has come from. It’s overly complicated, Windows support was clearly not a priority, and it switched existing VCS terminology around just for the sake of it a lot of the time. It practically shouts “I’m different, live with it!” at you, which is frankly a typical elitist geek attitude and not one I particularly respect. This attitude permeates the documentation, reinforced by the absolute insistence of most tutorials that you need to understand Git’s underlying data model before you start using it. Er, right – sorry, but when normal people want to learn how to use a new tool, we just want to know how to use it, not how it’s built. If understanding how it’s built is a prerequisite to using it, then I’m sorry, it fails miserably at being user friendly.

Nevertheless, it’s fast, it’s efficient in storage, it’s the most popular & fashionable DVCS (probably due to GitHub) and that has weight. Of particular interest to me is that TortoiseGit has come along in leaps and bounds, and is really quite pleasant to use. Of course, the reason it’s pleasant is because it hides the majority of the nonsensical changes that Git decided to make to existing VCS terminology; for example ‘Revert’ in TortoiseGit does what you expect (undoes your working copy changes), rather than needing to use ‘git reset –hard’, which is only intuitive to those who live on Mars (git revert, in contrast, records a new commit to undo a previous commit – why the hell do you need a special command for that??). Thus, it’s an odd situation – using TortoiseGit is pleasant, but only because it ushers the underlying git behind a curtain and gives you what most people really wanted from it in the first place. The downside is that using TortoiseGit really doesn’t teach you how to use the command line very well, like most other VCS tools do. In fact, it may well mislead you into thinking Git is friendlier than it actually is. For example, it saves you from the ridiculous need to remember the “-a” argument to “git commit” – without which what you actually get in your commit is the state of the file when you did “git add”, not the version in your working copy. If that makes sense to anyone, raise your hand. Thought not.

Hosting & collaboration wise, GitHub seems very good.

Mercurial

Mercurial on the command line is nice. It behaves the same way centralised VCS’s do, except in the cases where it needs to be different. This is pragmatic design – not being different just to make a point, but being different where it needs to be. It doesn’t break old concepts and does what you expect it to, and contrary to what some people think, that’s a very valuable feature.

It’s not all roses though. TortoiseHg is clunkier than TortoiseGit, despite being based on a more intuitive core tool. The UI just feels a bit wrong (like putting action buttons on the toolbar – who does that?), and I’ve sworn at it for being unintuitive more than once. The other problem is that the Mac GUI tools are not really that great either – MacMercurial only allowed me to do a subset of the operations I needed to do, and Murky just crashed when I tried it. GitX in comparison works quite well on the Mac.

So despite a more intuitive command line and core concepts, and a more pragmatic approach generally to DVCS for ‘regular’ people, when it comes to GUIs Mercurial lags a bit now. This was unexpected to me since it is Git that has traditionally been poor on the GUI front. There are also a few other minor issues like branches being totally permanent and needing to be globally uniquely named, which can make local experiments more cumbersome.

Hosting wise, BitBucket seems quite competent, if a little less polished than GitHub.

Bazaar

I’ve only just started experimenting with Bazaar, and so far I’m quite impressed. It has the pragmatic approach of Mercurial, but also has a built-in GUI which is really quite nice to use and leads you through the initial setup and configuration. There’s also TortoiseBzr which feels somewhere in between TortoiseHg and TortoiseGit. I haven’t tried it on the Mac yet. Performance was always the issue listed as the major downside of Bazaar, but this has improved since 2.0 and while it’s not as fast as Git, it seems to be fast enough.

The main downside for Bazaar is adoption. It trails both Git and Mercurial in terms of the number of people using it, and therefore adopting it for a public project would have the disadvantage of making people use a tool they’re less likely to already be familiar with. Also for hosting, Launchpad is quite new; it looks quite good, and has more features than GitHub, but it doesn’t have the option to host private projects (not an issue for Ogre of course) or a graduated commercial plan – you can self-host of course but that’s not as easy.

Conclusions so far

The sad fact is that none of the 3 are an instant win for me; they all have positive and negative aspects. Summary so far:

Tool Pros Cons
Git Fastest & most efficient
GUIs actually good
Popular
Command line overcomplicated & unintuitive
Mistakes easier to make
Mercurial Intuitive
Fairly popular
GUIs a bit rough in places
Bazaar Very intuitive
Built-in GUI good
TortoiseBzr also good
Not very popular
Statistically the slowest
Launchpad is quite new

So, I’m basically in a no-win scenario. If I pick Git, it’ll work fine via the GUIs but it’s too easy to screw things up when using the command line, and I’m bound to get annoyed at the needless obscurity from time to time. But, lots of people will be happy to use it. If I pick Mercurial, I’ll be happier with the overall core concepts & command line, but the rough edges on the GUIs are going to annoy me day to day. But, quite a few people will be happy with it all the same. If I pick Bazaar, I’ll be happy with both the core concepts and the GUIs, but being the least fashionable option almost no-one in the community will be happy that I picked it over the other two, and lots will bitch about having to use another tool.

I’m reluctantly acknowledging that the least of the evils appears to be Git right now, even though I personally hate its underlying interface. Somehow it feels wrong to only like using it when it’s hidden beneath a GUI – I’ve been a regular user of the command line for CVS and SVN for the best part of a decade, and I like being happy with both modes. I can imagine tolerating Git’s command line, but never liking it just because of the unnecessary idiosyncracies (like commit -a).

I still have lots more detailed tests to do anyway, which will have to wait a month or so until I have more time.

  • http://www.stevestreeting.com Steve

    Yeah, congrats on Bazaar Explorer, I really liked it.

    The thing that bothers me a bit about Bazaar now is the way branches are handled; that is that a repository path *is* the branch. This is quite like SVN on the server-side, but propagated everywhere, and I found when using it in a working copy that it felt a bit weird not being able to switch branches in-situ, and that merges could be done either via a push between branches or a ‘real’ merge, since branches are repos too. I’m not sure I could get used to that :?

  • http://ianclatworthy.wordpress.com/ Ian Clatworthy

    If you want a switchable working tree, just create a Checkout. To switch to another branch, use Work > Switch checkout.

    The Checkout can be under the repository (and Start > Init > Shared tree sets things up that way) though many users like to put their repositories/branches in one place and their checkouts elsewhere. It’s completely up to you and each user can choose whichever way of working they want.

  • http://ianclatworthy.wordpress.com/ Ian Clatworthy

    In Bazaar, branches aren’t repositories, though a repository will be created implicitly for a branch if one doesn’t exist yet. Working in a shared repository is highly recommended. Explorer 0.8.2 checks if the branch destination is outside a shared repository and offers to create one if it’s not.

    I’m not sure what you mean by using push to merge? To merge, use merge. :-) If you’re keeping a mirror branch up to date, use pull. Here’s the normal process:

    1. Grab a branch from a hosting site. Explorer will suggest making a shared repository. Agree to that and Explorer will suggest a name of ‘trunk’ within the repository for your mirror.

    2. Create a feature branch called ‘fix-123′ or ‘feature-abc’ by selecting ‘trunk’ in the repository view and selecting the Branch button.

    3. Work in your feature branch.

    4. When it’s ready to land, open trunk and pull to refresh it. Then merge your feature branch into it and commit.

    You can get fancy by doing stuff like working in a checkout or by making trunk a bound branch. To begin with though, the process above is what I’d recommend.

    The one place where push comes into it is where casual contributors don’t have write access to the trunk on Launchpad say. Then they push to a branch of theirs and create a merge proposal for the core development team to review.

  • http://www.stevestreeting.com Steve

    Thanks for the info. However “Switch Checkout” is always disabled for me and doesn’t exist on Tortoise Bazaar, which is probably why I never saw it.

    Also creating a branch doesn’t seem that obvious from within your own checkout. To create a branch, you have to select a source again.

    What I meant by pushing a merge is that because, when I created branches, they appeared to be just like any other repository and so I could push a change from one branch to another if I chose to, which just felt confusing. I would normally use merge too, but it was just an example of how the self-contained nature of the branches seems weird to me.

    I guess I’m not comfortable with the way branches exist in a pseudo-standalone way (as I perceive it), rather than simply being contained as a logical construct in the main repository. I’m sure it’s more flexible that way, but somehow I prefer branches to be bound in a containing repo rather than detachable as their own repo.

    I’m no expert in Bazaar, this is just my initial impression on playing with a few branches on my local machine.

  • Josh Jensen

    FWIW, StGit does preserve all patch manipulation history in a branch called branchname.stgit. It would be possible to retrieve an older version of the patch from that history, but it is somewhat ugly.

    What I would like to see is a view of the patch’s history itself, as if it were a branch. All the information is stored in branchname.stgit; I can see my prior commit. It just doesn’t show in a nice form within gitk (or if it does, I can’t figure out how).

    Ignoring that, StGit seems every bit as powerful as mq.

  • http://www.stevestreeting.com Steve

    In practice, I’ve actually found that Git’s cheap, private local branches are fine for handling these cases. I create a local branch or three (which are not linked to any origin branch) and build up unfinished patches there, and then merge them across to my main branch which I push upstream from when they’re ready. Works fine, and the level of control is actually very good. I find this infinitely more useful than the staging area because it’s multidimensional.

  • http://www.jacmoe.dk/ jacmoe

    I tried to answer you on Twitter, but here goes:
    Rebase is included with Mercurial, and you don’t have to enable it.
    When pulling, you have four options: nothing, update, fetch and rebase. It’s in the Synchronise dialogue. :)
    One extension you’d want to enable is hgext.win32text which fixes eol issues.

  • http://www.stevestreeting.com Steve

    I definitely did have to enable the extension before I could use ‘hg pull –rebase’ or ‘hg rebase’ on the command line. Standard Mercurial 1.3.1 just says it doesn’t understand the rebase command / option until you do that.

    I spotted that THg has the Rebase option in the ‘Pull’ dialog after I posted, but guess what – if you forget to select it during the Pull, you’re stuck. There is no separate Rebase option that I can find in THg, and you can’t repeat the Pull to do it because it does nothing when you’re up to date. The only way to resolve it at that point is to use “hg rebase” on the command-line, which like I say does not work unless you enable the extension.

    [edit]I think that the upcoming THg 0.9 supports a separate Rebase and Transplant, which will be welcome since TGit makes these operations much easier.

  • http://www.jacmoe.dk/ jacmoe

    Ah – I think I got it because I’ve enabled the mq extension. :)
    Yep, that’s it.
    You can select the default pull action somewhere in the highly intuitive (not) configuration dialogue. ;)

  • http://www.jacmoe.dk/ jacmoe

    In your Mercurial.ini (In Windows, that is – .hgrc on *nix)
    put this:
    [tortoisehg]
    postpull = rebase

    This is my list of extensions:
    [extensions]
    hgext.win32text=
    hgext.mq =
    transplant=
    color =
    hgext.bookmarks =

    Transplant is great. :)

  • http://www.stevestreeting.com Steve

    Thanks, that’s useful. However I do kind of like to do *just* Pull and then check what changes are before I decide what to do, rather than always rebasing. Especially if I have multiple branches active.

  • http://www.jacmoe.dk/ jacmoe

    Hint: Use ‘Incoming’ first. It’s like a sneak peak. :)

  • Rob

    The -a thing makes a lot of sense to me. It has to do with working in terms of patches. We’ve switched to git at $work and a lot of times, I have a gazillion debugging statements in various files. I want to commit a fix for one of the three variants of the bug I’m working on, but I don’t want to have to back out all the warning statements I’ve added for tracing because I have two more variants to hunt down.

    Yes, it takes a little getting used to sometimes. But, that’s not a bad thing.

  • http://alen.mobi Tero

    I made same kind of evaluation for some time ago and my choice was Mercurial: http://alen.mobi/blog/2009/07/30/i-prefer-mercurial/

    I have been using Git and I didn’t really like it’s cli interface. After Git I tried Mercurial and it was really pleasant to use because I come from Subversion. I haven’t used any GUI tools for version control, so I can’t say anything about them, but from command line Mercurial rocks :)

  • http://www.jacmoe.dk/ jacmoe

    Steve’s leaning towards Mercurial now – read this:
    http://www.stevestreeting.com/2009/11/06/dvcs-score-card/

    And the topic @ the Ogre forum:
    http://www.ogre3d.org/forums/viewtopic.php?f=4&t=53129