Building notes, projects, and occasional rants

I don't need no stinking branches

A friend of mine was teasing me last week about my recent posts about Git, and wondered why am I using distributed Source Code Management (SCM) system for all my projects, even those where I'm the sole developer. He is not the first and I tend to have the same conversation with all of the ones who ask me about it.

Usually I start by telling them about offline-mode and the fact that I spend a lot of time off-the-net, which ends up being the least important reason.

Then I usually talk about the fact that I get backups for free because I can just push my work to far away servers.

But one thing gets the discussion a couple of degrees hotter: branches.

What I notice in these encounters is that they just don't do use them at all. And the reason is simple. Most of them used CVS and moved on to Subversion. With CVS branches where possible, and with Subversion, branches became easy and cheap. What both of them failed spectacularly at was merging.

There are situations where you branch not to merge "ever" again, like the maintenance or stable or stabilization branch approach. Those who look through a Subversion timeline of a project that uses maintenance branches will get accustomed to see commits in trunk with the cute message "Back-ported rNUMBER to trunk". What that means is that some changes in the maintenance branch where applied (not merged) to the trunk.

So now you have two commits exactly the same, one in the maintenance branch and one in the trunk, when you should have just one.

With care, you can use branches for real work, and merge to the trunk at the end. But in Subversion for example, you have to tell them what revisions you want to merge. So the branch is not an entity that you can manipulate. It's not a container. You, the developer, have to be the one that figures out what revisions need to be merged. And if you code a little bit more and want to merge again, you have to tell him to merge only the new revisions. And one side-effect of this kind of merge is that your beautiful history of the branch, explaining why things where done the way they where, is lost because the merge ends up as single huge commit.

You can play games with tags to help you. You tag the root of the branch with branch-root. When you need to merge, you just merge the differences between branch-root and branch. And then you'll tag the branch again with branch-last-merge-DATE, so that the next time you want to merge, you'll use the most recent branch-last-merge tag to compare the branch with. This works, I was doing this with CVS 5 years ago, but its painful.

So, with this lousy system of merge tracking, its no wonder that explaining the use of a different branch for each feature you develop and merge them into a staging branch for testing and then if all goes well merge that into the mainline branch for deployment, you get these eyes that say "Are you crazy??".

I'm not crazy, I just moved on. I refuse to be abused by inferior systems like CVS and Subversion no matter the following and success they have. Life is just to short.

Systems like Git and other decent distributed SCMs allow me to treat branches as containers of change-sets, containers that I can manipulate as a single entity and tell git-merge branch master repeatedly and have him "do the right thing" every time. It allows me to experiment new features without fear of messing up my repository, and knowing that if all goes well, merging back the changes will be easy. And if not I can always drop the branch.

So, if you decide to try one of these systems, please don't use it as a better Subversion. Make sure to abuse the new power, of branching, of merging, and split your work with topic branches.

The pasture is really greener on the other side of the fence, so hop over and grab a nice chunk of grass.