Thursday, January 29, 2009

Figuring out a branching strategy

To be honest, before I started working at Frogmetrics, I didn't know how project branches were managed. I was working at a research lab, and most of what we did was prototyping. After we demonstrated that it worked, we threw it over a wall, and then it was someone else's problem (poor them). A lot of the time, I was doing work on my own, so there was no (perceived) need for source control. The only time we used source control was when I was working on the New Horizon spacecraft. And even then, someone else managed the branches. Because it was SVN, we all mainly worked off trunk.

Until recently, I never contributed to an open source project either. Therefore, I really had no idea when to branch. So when we started working on the analytics, we really had no idea what a good branching strategy would be.

Googling didn't help, because either everyone else doesn't call it "branching strategy", or everyone already knew how to do it. I eventually figured something out though.

Last week, after talking to AJ of Scoopler about git, he ended up asking about branching strategy. It became apparent that branching strategy wasn't an obvious thing, so I decided to write something here. This is obviously not the only way to do it, so if you have other suggestions, by all means, comment.

At first, we didn't know what we were doing. We knew that we wanted to have a branch that had the same code on the production server, and another branch where we're working on the 'next' version. So we had a branching strategy that looked like this:

As you can see, we branched every time we deployed weekly. This gave us the option of doing bug fixes on the every deploy version, while keeping a working branch. However, this was a terrible way to do things. This branching strategy required you to keep merging back bug fixes that you had made earlier. In addition, we were using bug tracking software to track all the issues from week to week, which results in much ticket shuffling and overhead.

Now, we're doing this. Locally, we still branch for every feature that we're working on. And when there's a major set of features that need to be implemented by more than one developer, we create a remote branch for it that we push and pull to/from.

Thus, we're treating master as the golden copy of the code base. It is always deploy-able, passes all tests, and is perfect code as we know it. This allows us still the advantage of doing bug fixes and deploying independent of what features are currently on deck or in the hole, and yet we don't have to do merges every time are about to do a new version. We simply (and somewhat arbitrarily) tag versions as we go along, and only merge feature branches back. When we can, we rebase the branches to keep the history clean. In addition, we try to make our commits atomic and about one thing, rather than one feature set. That way, it makes it very helpful to remove a piece of code, cherry-pick a changeset to another branch, or find an offending commit that broke something.

So far, it's worked pretty well, but it might evolve as we go on.

Well, hope that helps. This post wasn't as fun to write, but it was something I hadn't see too much of out on the web, so I figured I'd contribute. Fun times.

1 comment:

  1. Laura Wingerd from Perforce wrote a presentation on this topic that I think everyone using distributed version control should read: http://www.perforce.com/perforce/conferences/us/2005/presentations/Wingerd.pdf

    ReplyDelete