I am officially sick of DVCS

We use Mercurial at work.  It’s nothing particularly new to me; I’ve been working with it ever since SDL, a major open-source graphics library that I’ve been using and contributing to for a long time now, changed over to a HG repository several years ago.  You’d think that I’d be used to its quirks and glitches, all the little things it manages to somehow not get right, by now.  But it keeps finding new and innovative ways to suck.

Yesterday at work, I was halfway done with an issue when a very minor but very urgent issue came up: I had checked in something that was breaking the build.  No big deal, right?  Just fix it, check in your changes, and get back to work.  Well, yeah, that’s how it would go if you were using a sane version control system like SVN.  But we use Mercurial at work.

The “just fix it” part is the same, but then I went to check in my changes.  In SVN, this is incredibly simple: select the changes to check in, write a commit message, click OK, and you’re good.  But Mercurial is a DVCS.  It was designed for much larger, more complicated projects than most people will ever work on, stuff like operating systems, that are so huge that distributed repositories are a necessity.  (I heard it said once that if every developer on the Windows team were to only ever break the build once per year, they would literally never have a working build if everyone checked into the same repo.)  But we don’t have a team anywhere near that huge.  And yet, we use Mercurial at work, and it likes to pretend we need all the stuff that enormous teams need.  So checking in code is a two-step process as a best-case scenario.  First you commit it to your local repository, then you push your local repository changes to the central repo.

This turned out not to be the best of times, because someone had checked in something since the last time I pulled changes.  In a sane VCS like SVN, this doesn’t matter all that much; you just grab the update, SVN integrates everything seamlessly unless there’s a merge conflict–which is rare in a well-managed project regardless of which VCS you’re using–and then you commit.  For a couple years now, TortoiseSVN has even been able to automate that workflow for you.  But we use Mercurial at work.  So you pull the changes to your local repo, and then you have to “update” to that revision, even though that really should be a no-brainer.  Except that I have a commit in my local repo, and even though they’re on the same branch, Mercurial freaks out and turns it into a new branch of the branch I’m on.

That’s not a problem, right?  Just merge the commits.  Except Mercurial doesn’t know of any such thing as “merge commits.”  No, it knows how to “merge with local”, meaning it pulls the new commits on the new branch into your local working copy and then commits the changes from your local working copy into the local repository.  This sounds like a pointless semantic difference, and there really shouldn’t be any difference at all, except… I was in the middle of working on another issue, so I have uncommitted changes.  For some moronic reason, if I try to merge, HG will commit those to my local repo too, and then you’re stuck in a huge painful mess of trying to back your changes out, because HG doesn’t know how to merge two commits and only merge that.  And yet we use it at work.

No big deal, though.  Any experienced DVCS victim can tell you how to take care of that scenario: just shelve your uncommitted changes before you merge.  Nothing I haven’t done dozens of times before.  So I dutifully stick my uncommitted changes on a shelf named “Mercurial is stupid”, which is the one I use for performing this stupid operation that would not be necessary if DVCS wasn’t fundamentally broken.  (Yes, DVCS in general.  Git is even worse about these things!)  I merge the commits, push my changes, and everything is peachy… right up until I go to unshelve my code and get back to work.

You see, one of the changes I had made involved renaming one of the units in the project.  Since Delphi requires the unit name declared at the top of the unit to match the filename, this means both changing the code and renaming a file.  I had dutifully renamed the file using the special Mercurial operation for it in the context menu, so that it can track the changes correctly.  But when I go to unshelve, the operation fails.  It says “NewName.pas” cannot be found, and therefore it can’t apply the changes to the unit name declaration at the top of the file.  (But it very helpfully restored the deletion of the old file, which meant I had to go back and revert the change and do it all over again!)  So much for being able to track renames properly!  What’s the point of even having an official Mercurial file rename command in the context menu if it doesn’t actually know that the file has been renamed?  Even my manager, who actually likes Mercurial, had wasn’t sure if there was any easy solution.  He had never seen this before and he was all confused when I showed this to him, because he didn’t know it can screw up in this particular way.

Every time I think I’ve seen it all, DVCSs keep finding new and innovative ways to suck.  The entire DVCS concept is essentially a fractal of bad design, and the deeper into it you go, the more problems you find.

And yet, we use Mercurial at work.  I guess I’m stuck with it.  But please, if you happen to be a manager setting up a new project… just use SVN and save everyone a ton of headaches!

29 Comments

  1. Kyle Miller says:

    Couldn’t you Cherry Pick the commits you want into local? It’s built into Git and an option in Mercurial.
    http://thingsilearned.com/things/cherry-picking-with-mercurial

  2. Darian Miller says:

    Bravo. “DVCSs keep finding new and innovative ways to suck.”

    • Kyle Miller says:

      Darian,

      This sounds like a lack of familiarity with DVCS. Now, I’m speaking from a more Git than Mercurial experience perspective. I would be surprised Mercurial does not have equivalent solutions for the challenges he faced.

      For instance, merging remote commits into local working copy on Pull. Completely possible. From my Git tool of choice…
      “This will open the Pull dialog, where you can specify what SmartGit will do after the commits have been fetched: Merge the local commits with the fetched commits or rebase the local commits onto the fetched commits.”
      http://www.syntevo.com/doc/display/SG070/Synchronizing+with+Remote+Repositories

      “I was in the middle of working on another issue, so I have uncommitted changes.”
      In Git, you should start a new local feature or issue branch for each issue. It’s easy in SVN to juggle multiple issues in a single working copy, but it has its pros and cons. You can do the same in Git, but it is not necessarily proper for non-trivial work. Git tools support Git Flow and make it trivial to get a clean slate and begin work on a new issue. See Git Flow commands here…
      http://www.syntevo.com/doc/display/SG070/Git-Flow

      And while DVCS can and does work for large teams does not mean it can’t fit for smaller teams. You just trim workflow where it makes sense. For instance, you can use the entire Git Flow workflow. For smaller organizations, the Simplified Git Flow might be a better fit.

      Using DVCS is more than learning something new. It’s a mind shift. If you approach DVCS like SVN, you’re going to be disappointed.

      • Mason Wheeler says:

        For instance, merging remote commits into local working copy on Pull. Completely possible.

        Yes, Git does better than Mercurial on this… as long as you don’t have any uncommitted changes at all. If you do, panic ensues and it will refuse to merge anything at all, even if none of the files it’s pulling in are the same as any of the files in which you have uncommitted changes. (Isn’t “better merging” supposed to be one of the big selling points of DVCS? Seems to me that’s a blatant lie; SVN is the only major VCS I’m aware of that doesn’t make you go well out of your way to work around its deep-seated fears of the VCS having to ever locally merge anything ever.)

        In Git, you should start a new local feature or issue branch for each issue.

        Where does this idea come from? I’ve heard it repeated various times, but I follow a ton of different projects on GitHub and I have never once seen anyone actually do this.

        If you approach DVCS like SVN, you’re going to be disappointed.

        Yes, if you approach a broken system expecting it to work like a system that works, you will be disappointed, because it’s broken.

        • Dalija Prasnikar says:

          I agree with Kyle Miller. DVCS are not broken, they are different.

          > > In Git, you should start a new local feature or issue branch for each issue.

          > Where does this idea come from? I’ve heard it repeated various times, but I follow a ton of different projects on GitHub and I have never once seen anyone actually do this.

          Because those branches never get pushed to public repo as separate branches.

        • Kyle Miller says:

          “Where does this idea come from?”

          Note that you don’t have to create a branch for every issue you work. You could create a local branch for each track of work being worked. If you work on up to 3 issues/projects at a time, create 3 generic local work branches which get merged back to trunk and then pushed. (Only the changes merged to trunk get pushed, not the local branches, if you merged it to be so, e.g. a rebase or squash merge.) The benefit to this is independent issues remain independent tracks of work. No need to worry about intermingled files, i.e. commit these and not those and maybe those. And if UnitCommon.pas is touched by two issues you are working, each issue keeps its own copy of the file. You won’t be in a situation where 10 line changes belong to this issue and 15 belong to that issue. No file with a hybrid of changes.

      • Darian Miller says:

        From what I’ve seen before, the typical instant reaction to the declaration of someone disliking Git is that the person obviously doesn’t know enough about Git to really know any better and others are compelled to correct their mistake.

        After a few years of using it sporadically, I’m familiar enough with Git to know that I sincerely dislike using it. I use Git almost exclusively with GitHub projects. I have used HG with BitBucket and Kiln in the past. Fossil is interesting, Plastic is pretty powerful, but SVN is the choice for me.

        It’s a hotly contested topic, and many others have ranted online as well. Here’s a few:
        http://stevebennett.me/2012/02/24/10-things-i-hate-about-git/
        http://stevelosh.com/blog/2013/04/git-koans/

        Bottom line – use the tool most appropriate for the job. If Git is getting in the way of productive work, then ditch it. If you are struggling with tons of small branches and find yourself lost in SVN, then learn Git and you actually may benefit. But in many cases, “DVCSs keep finding new and innovative ways to suck” is quite appropriate. I’m glad you like Git but that doesn’t mean I have to, and it certainly doesn’t mean I need a mind shift.

        So I repeat, ‘Bravo’ to someone who (assumedly) knew exactly what sort of response he’d receive from Git enthusiasts as it was obvious to me what was coming as soon as I read it.

        For fun, I’ll also state “Merging is inherently evil” and I’m sure that there will be an overwhelming inclination by some to educate me on how easy merging is with Git. I’ll concede up front that in many cases it certainly is easy with Git, but in many of those particular cases, it’s also easy with SVN.

        Rules to live by to stay productive: keep your branches to a minimum, check into the mainline often, merge only when you have to, and concentrate on your task, not your VCS…and, “Don’t Worry, Be Happy”
        Cheers!

        • Kyle Miller says:

          It’s okay to use your preferred tool or use the most appropriate tool for the job. But, choosing one tool over another because of inexperience or misunderstanding is ill advised.

          I’ve seen the 10 Things I Hate About Git article. It is illustrates the problem of having an SVN approach to DVCS. For instance, he fails to understand Git provides 2 things: version control (local & remote) and workflow facilities. He points out Pull Requests being an extra step.

          1) Pull Requests assists workflow. It allows committer to requester review to review and test the work before committing to trunk. What’s SVN’s solution? Make a patch file, email to reviewer, apply patch file, and proceed with review and testing. The author leaves all of this out when discussing SVN in item 10.
          2) Pull Requests are optional. If you believe integrating this review facility makes version control too complicated, don’t use it.

          Another problem with the blog article is its bias against Git. For instance, in the final outline of what he says you have to to do Git, his first step speaks of starting from the baseline. Is this a bad thing? Do you not want the same with SVN?

          Last but not least, he illustrates several steps involved in using Git. Git will introduce a few more steps and not all he showed is required. (If Github used SVN, a complex graphic could be created just the same.) But, the extra steps are the price you pay for having local version control and remote version control. The extra price of local versioning is worth it given what you can do with it, e.g. working independent issues touching the same source files.

          I read the 10 Things article will I was researching the VCS landscape. Anti-Gitters are quick to point to that blog entry are proof of its weakness. What is interesting is how there are hundreds of pro-Git articles they refuse to acknowledge. The very few articles against are all the evidence needed to disprove Git’s worth. Really?

          I could write the many things I can’t stand about SVN, but why? It was written at a certain time to solve particular problems. It just does things differently.

          • David Novo says:

            One of the issues may be the difference between using a D-VCS when the team is distributed, vs when the team is not. When the team is distributed, you really have may not have any option but to use a D-VCS. Or at least it makes some things much easier.

            But when the team is not distributed, the DVCS seems overkill to me. Per your previous comment

            “It allows committer to requester review to review and test the work before committing to trunk. What’s SVN’s solution? Make a patch file, email to reviewer, apply patch file, and proceed with review and testing.”

            uh, no. Using your issue tracking system, assign the issue to the reviewer for review. The reviewer has a choice to switch to your branch to review changes, or just review changes from the repo browser (i.e. navigate to your branch and use the log to review changes). Or just use TortoiseSvn to compare the branch and trunk and it will show all the files that are different and you can see the diffs.

            I have no idea where this conception that you should not have branches in SVN or that should be “rare” things. We have about 12 developers, each is working on a branch for their own issue. They merge from trunk to their branch on a daily basis. When they are done their branch they reintegrate. We have no hassles. There is the occasional conflict that is usually easily resolved.

            In a system that is centralized anyhow, the DVCS brings limited, if any benefits in my opinion. But does bring a cognitive burden of pushing, pulling, etc that does not exist with SVN.

            • Kyle Miller says:

              Creating separate branches in the central repo for each developer (and assuming work branches from there) is not desired because it creates cruft. Also, handicapping if I want to do work and commit as I go and the central repo is unavailable.

              Pushing and pulling are concepts SVN users have to deal with too. They are called SVN Commit and SVN Update. The diff between SVN and Git is Git has local commits which take place before a push.

              • David Novo says:

                You do know you can delete branches you are not using any longer right? Even in lowly SVN. So there really is no cruft hanging around. Even with a DVS many people push all the changesets to the central repo, and do not rebase, so the intermediate steps are still hanging around.

                This silly argument of “at least with DVCS I can work when the central repo is down” is the mirror of the equally silly argument “with DVCS you lose 3 weeks of changes when the user who has not pushed his changes has a hard drive failure”. Both are real potential problems, and both are easily mitigated with fairly easy adherence to best practices.

                It is strange that the DVCS people seem to always take the position that DVCS is best under all circumstances at all times (even when you dont have a distributed environment at all) whereas the SVN adherents seem more reasonable in noting there are pros and cons to every solution, even a DVCS.

          • Darian Miller says:

            I only referenced those articles to show that there are others that don’t like Git…There aren’t just two articles out there, just two I found quickly and I thought the second one was quite unique.

            If you want a different reference from a different viewpoint… to quote from a well known source, “Continuous Delivery” by Humble/Farley with a forward from Martin Fowler (who has written about mainline methodologies.) This is one book in about a dozen within easy reach of the desk. In the Continuous Integration Chapter 3 section on DVCS:

            “..This model takes the possibilities of DVCS to their logical conclusion.
            These alternatives to continuous integration can create high-quality, working software. However, this is only possible under the following conditions:
            – A small and very experienced team of committers who manage pulling patches, tend the automated tests, and ensure the quality of the software
            – Regular pulling from forks, so as to avoid large amounts of hard-to-merge inventory accumulating on them. This condition is especially important if there is a strict release schedule, because the temptation is to leave merging till near the release, at which point it becomes extremely painful – the exact problem that continuous integration is designed to solve.
            – A relatively small set of core developers, perhaps supplemented by a larger community which contributes at a relatively slow pace. This is what makes the merges tractable.

            These conditions hold for most open source projects, and for small teams in general. However, they very rarely hold for medium or large teams of full-time developers.
            To summarize: In general, DVCS are a great advance…DVCSs can be extremely effective…However, we caution against using these patterns when the right conditions, listed above, are not satisfied.”

            Now, you can state how great Git is, and how uninformed the haters are, but that does not lead to the conclusion that all haters are uninformed.

            To broadly group everyone into two groups of “Like/Understand Git” versus “Don’t like/Don’t Understand Git” fails to realize a number of other possibilities such as “Understand/Cost-benefit analysis of current team practices says no” or “Understand/Need more fine-tuned access control” or “Understand/Need hosted+supported version with enterprise features that’s less expensive than GitHub Enterprise” or simply “Understand/but team is much more productive with other tools and they would break out pitchforks and torches if the team switched to Git” …and obviously many of other perfectly valid reasons as well.

            So again, “Bravo” for “DVCSs keep finding new and innovative ways to suck.” And it’s not just because I am completely uninformed. It’s because I live in a different reality and I simply don’t want your reality, right now. I don’t need your reality, right now. I purposefully, thoughtfully, and wholeheartedly reject your reality with a gleam in my eye and a skip in my step. But, thank you anyway. It’s not meant as a slam – you do yours, I’ll do mine. Perhaps in a few weeks/months/years, the situation will change, the flow will require a different management style to achieve better results, and we’ll switch to something else and Git will certainly be a consideration and not tossed aside based on my personal feelings on how it can suck harder than a Dyson at times. But, that will hopefully be based on purposeful intent, not simple desire to use a different technology because the smart kids say so.

            Now, perhaps it’s simply because I’ve been working on the same piece of software for 20 years, and I am too set in my ways…I’ll admit that, but my choices have also kept us running for 20 years so regardless of what’s written on the blogs, or in the books, or who it’s written by…as they say, “the proof of the pudding is in the eating”, and I’m still here after 20 years so that says something – and I eat fairly well.

            Cheers

  3. Natalie Vincent says:

    I feel your pain. To top it all off, mercurial likes to corrupt it’s database on my machine on a regular basis, and the suggested fixes usually include hand editing files (!)…

    Anyway, the way I get around the uncommitted changes thing is to make a new clone of the repository locally and do the changes in there and push them up. Then I nuke the repository.

    N@

  4. Roman says:

    Mason,

    I have the impression that you making two mistakes:

    1. You should use TortoiseHG and its workbench. It is a very powerful tool and it is more offers more comfort than TortoiseSVN.
    2. You should work with branches and reviews.

    The point 1 is the reason why I do not want to work with GIT. And if you work with branches, reviews and the great merge possibilities you will forget about SVN.

    If you are interested I can show you some practical examples about it. Simply send me a PM.


    Thanks,

    Roman

    • Jacek says:

      Well, if the first point is a reason to not use, then please look what a workbench offers SourceTree for git (is also supports Mercurial, BTW).

    • Mason Wheeler says:

      I am using TortoiseGit and Workbench. (Can you imagine what a horror it would be if there was no GUI?!?) But what do branches and reviews have to do with Shelve glitching out?

      • Roman says:

        You are using TortoiseGit and Hg?

        I’m maintaining some libs that are hosted under GitHub and since GitHub only supports Git I have to use Git.
        I played a bit with TortoiseGit and think that it only offers a fraction of what TortoiseHG offers.
        That’s why I’m using TortoiseHG with HG and Git but for sure it works much better with HG than with Git.

        From what I read I have the impression that you are fixing several issues in the same (main) branch. That’s why I think you should work with branches.

        BTW; I thought that you are working for David, aren’t you? But David uses SVN, doesn’t he? So I’m a bit confused.


        Roman

        • Mason Wheeler says:

          Argh, typo. I’m using TortoiseHG and its Workbench. And no, I’m not working for David anymore; I changed jobs last year. At the new place, we use Mercurial.

          • Roman says:

            I see.

            But why don’t you work with branches? And I mean not named branches but multiple repositories instead. Then you do not have the problem with the not finished units that must be checked in before you can merge.

            • Mason Wheeler says:

              Are you serious?

              My thesis is that the workflow is pointlessly overcomplicated. In SVN, resolving the scenario I described is about as simple as it can possibly get:

              1) Commit
              2) Can’t commit, because there are remote changes you don’t have
              3) Update
              4) Commit

              This pattern is common enough that TortoiseSVN automates the last 3 steps for you, turning the whole thing into 3 mouse clicks. And then you’re done and you can get back to work.

              Here’s the workflow in TortoiseHG:

              1) Commit to local
              2) Push local to remote
              3) Can’t push, because there are remote changes you don’t have
              4) Pull remote changes (you have to do this all manually)
              5) Remember that you can’t merge yet because you have to shelve first. (Yes, this is its own step, because it’s a part of the cognitive load of the process. If you don’t do it, things get even worse.)
              6) Shelve.
              7) Merge branches and commit the merge to local
              8) Push local to remote
              9) Unshelve
              10) Find out that unshelve is broken because it didn’t track your rename right
              11) Revert the delete of the original file that it deleted rather than renaming.
              12) Open that file’s location in Explorer and repeat the HG Rename operation
              13) Open that file in your editor and repeat the changes you made
              14) Delete the pointless .rej file TortoiseHG left behind

              And you say that this can be fixed by making a copy of the entire multi-gigabyte repository?!? “Oh, you injured your hand? We can save you the trouble of all those annoying details of caring for the wound by simply chopping your arm off.

              Are you serious?

              • Roman says:

                I do understand what you would like to say. A DVCS is completely different to a non-DVCS.

                One point is that in a DVCS you shouldn’t work with an entire multi-gigbyte repo because of the cloning stuff whereas huge repos a normal in SVN.

                Another point is that branching is normal in HG but in SVN it is an exception.

                In HG I’m working with subrepos, in SVN I never used externals.

                In SVN I added for example bmps to the repo, in HG I don’t because the repo should remain small.

                In SVN everyone adds everything to the main (trunk) branch whereas in HG everything is added to an own branch. And after a review we decide to merge the code into the main branch.

                This means that the complete workflow with a DVCS is different. And if you don’t like this workflow, don’t get used to it or if it simply doesn’t fit then maybe it doesn’t make sense to use a DVCS. Then SVN would be better for you.

                And yes, I’m completely serious. I worked with both, SVN and HG, for many years but I moved all projects to HG and skipped SVN.

                • David Novo says:

                  Hi Roman,

                  Why is branching an exception with SVN? I never understood this idea. We branch, merge and reintegrate all the time. Sure, we dont stay on a branch for 6 months without merging from trunk. Maybe that is more possible with a DVCS, but I still dont think its a good idea. With daily merges from trunk to your branch, we never find reintegration a problem. We probably have at least 8 branches active at once for different projects that developers are working on. They make their changes, run a full test case suite, and when the tests all pass, reintegrate to trunk.

                  • Roman says:

                    Hi David,

                    In the past I had problems to merge branches into trunk. Sometimes I had to merge my changes manually but maybe I did something wrong. Because of this I normally added my changes into trunk. With HG it is for me much easier to merge.

                    At one customer I’m working with three main branches, Release, Beta and Develop. And we have no problems to merge bug fixes from Release down to Develop. Normally after a month we push Beta to Release and Develop to Beta which works perfectly with HG. We are also working with new branches for changesets and create reviews before we merge into one of the three main branches. But for sure if a branch is 6 months old you normally can’t merge it without changes.

                    But if the SVN workflow fits perfectly to your work then I think you shouldn’t move to HG. If your svn repo is available from outside I also think that it should work if someone wouldn’t sit in LA.

  5. Roland Bengtsson says:

    I use Git against github with a small team of 5 members.

    Yes conflicts happen sometimes if someone commited a file you working on.
    But is is just to manually edit my local file, mark the issue as solved and then commit.
    One thing thta we learned is that it is important to pull often to keep those conflicts away.

  6. Leonardo Herrera says:

    I had to be dragged kicking and screaming from SVN a few years ago, but now I cannot imagine going back. I’m not impressed by your rant, sounds like you are too used to old manners.

  7. David Robb says:

    Hi Mason,

    I use multiple local repositories to handle different (simultaneous) tasks and to ease the kind of task switching you refer to. Shelving is time-consuming and IMO unnecessary because a repo can be repurposed for a new task once a given task is completed. Usually all you need is 2 or 3 repos to handle task switching.

    Multiple repos have another advantage: since the IDE stores the local project configuration in the same directories (I am referring to dproj.local), each repo will have its own IDE local data, so if you load different files in a project in one repo, it won’t affect the files you have loaded in your project repo.

    Hope to help,
    Dave

  8. Robert Harvey says:

    I couldn’t agree more with your thoughts on DVCS in general.

    We use Git where I work, and even though I want to like it, working in it always seems to be just a tad bit more complicated than it should be to get anything done, unless I’m the only one working on a branch. Shouldn’t source control get out of your way so that you can get real work done? I think it should.

    Only software developers have the skills that are required to make things this complicated.

Leave a Reply to Dalija Prasnikar