If you've used revision control much before, and/or worked on a project with a lot of people simultaneously, you have probably been exposed to branching. I reflected a little on how we use it at work and how I use it, and thought I'd write it down.

Revision control is when you get some sort of system to keep track of the entire history of a set of files. For example, all these blog entries are stored in an RCS on my computer at home. I don't feel pressure to make changes to them, because I know the system is remembering everything they ever said.

A "branch" is just a copy of the files, but it's a copy which the system knows originated from some earlier version, so that you can pinpoint a time where the branch split off and diverged from the "trunk", as it is sometimes called. Branches are useful for several things.

The two main uses I see branching used for at work are freezing a version of the code and separating risky features. When we ship a version of our product, as we near the release, we fork a branch off of the trunk where the code is meant to sit with relatively little disturbance until release. Any high-priority changes that absolutely must happen will take place in that branch, while the trunk of the code may continue with the normal rate of change for work beyond the upcoming release. When we ship, we freeze the branch, and that's that.

We also use branches for keeping risky features or large chunks of work a little removed from the trunk. The reason we do this is that we build the trunk nightly, so that every day there's a new installable product for the entire team to test out and use. If large, complicated changes are taking place in the code, the probability that a serious bug arises in the product is high. If this happens, then the bulk of the team suddenly doesn't have a new build that's usable that day. It can halt progress for a day, so it's worth taking precautionary measures.

What happens is that we create a branch of the code that is to be used for the development of one of these "risky features." Changes are added to that version and not to the trunk version, so while the major problems are being ironed out, only the few people working on that feature are affected, not the whole team. Approximately nightly, all the changes in the trunk are merged down into the feature branch, so that the code is still mainly in sync. Periodically (every several weeks), the code in the feature branches is merged up into the trunk if it is of high enough quality, i.e. it passes a bunch of tests. At this point, the trunk and the feature branch contain exactly the same contents.

An interesting idea that came up in our last development cycle was the namingof our team's feature branches. In the product cycle before that, feature branches were named after the features developed within. But in this one, the feature branches were named after colors. Red, green, yellow, etc.. I asked one of our development managers about it when the announcement was made, and one of the answers he gave me is so that we wouldn't have any problems putting any feature in any branch.

This didn't make much sense to me at the time. It felt kind of arbitrary, but now, over a year later, I think I kind of get it. As a programmer, naming is important to me. Sometimes I spend an inordinate amount of time agonizing over how to name something, because if I use a name I don't like, it continually irks me afterwards. Likewise, having neutral names for feature branches eliminates the part of the brain that says, "we can't do this work in that branch, because it's intended [due to its name] for this other kind of work."

I adopted this for my MUD. Even though I'm just a team of one, I have larger features and smaller changes. I like to keep a stable trunk build all the time, so I use a "feature branch" called "blue" for my bigger items. For instance, all the work on socials and pmotes went into blue first, then merged into the trunk. Meanwhile, I made bug fixes for things unrelated to that feature in the trunk and merged them down.

I almost think of this usage as a third way of using branches. If you consider that the trunk is all that really matters, and if you like the idea that the trunk is always stable, and if you like the thought that features are added to the trunk as a single revision, this use of branching kind of satisfies that. Even though the feature really is too big to add all at once, all of the little iterative pieces are added in this branch, kept out of the way of the trunk. Eventually, when it's all ready to go, it's added as a single big change to the trunk. You kind of get the best of both worlds: granular additions, and a nice clean view of the trunk. Plus, if you need to revert an entire feature, you have a single change (the merge) to undo, not a ton of little ones.

I use revision control for everything. I can't imagine getting along without it anymore.


leah said...

this reminds me of how i use layers in photoshop in a lot of ways.

Post a Comment