Wed 10 Oct 2012
In a previous article, I mentioned that you could contact me, that I’m always here working on my manifesto. One of you mentioned you would read a version control manifesto. So, while I wait for the coffee to soak in enough that I can code today, I thought I would work on it. Since manifestos, to my knowledge, are long rambling documents without a lot of structure, I figured I would just jump right into the middle, and discuss a topic as controversial as any political arguments we might have going on in our country at the moment. Obviously, I’m talking about branching.
Branching is a fantastic concept that allows you to split your code base when you need to create a complicated feature, or fix a complicated bug, but still have the benefit of version control. When you are done, you can merge it back into the main branch (referred to as the “trunk” – I think it must be a pine tree, I’m not sure it works otherwise… it might be OK for oak, but it can’t be one of those trees that splits into branches and the trunk stops going in a straight line through the middle).
Different version control systems have handled this concept different ways. Some (cough-sourcesafe-cough) just sort of didn’t do it. This is how a lot of rock bands reacted to disco – they pretended it never happened and just kept doing what they always did. Not all of them though.
If you’re not used to using branches, don’t be scared of it. Branch the whole thing (don’t try just doing a few files, even if it is all you need). But you do need to know how your version control system handles branching. I will not be teaching you. But I will mention what a couple of them did wrong, maybe yours (provided you are using CVS or Subversion).
CVS let you create branches with names – but unfortunately it created them with really confusing long numbers – the same way it did everything else. Also the syntax to do this was bit of a pain – I honestly don’t remember it exactly – but you had to use the “tag” command with the “-b” option for branch, but not “-B” which meant something different (obviously) . It was easy to look at a number and tell that it was a branch, but it was rather difficult to pair that number to the actual human readable name for the branch. Sometimes you have to do this, particularly if you are writing support for CVS at a company that produces a programmer’s text editor. But what it did right was make it easy to see all the versions of a given file, across branches. So if you are looking for a fix that was in some version of /path2/path2/file17.cpp, but you then realize that fix might have been in a different branch, it was easy enough to look for.
If you knew enough command line options, you could merge two branches together. I don’t remember how to do it, I’m not going to look it up. I never completely trusted it. I would check out both branches, use our multi-file diff to compare/merge them, and then commit. It might have worked fine, but I found the options very confusing. Also, learning to trust tools to perform complex operations for you is a process.
Subversion lets you create named branches that stay named (as far as we can tell). Creating them is very intuitive, it has a “cp” command that we’re all used to (that’s the same as “copy” for the Unix impaired (for those of you who may be very young, it’s the same as right clicking on a folder and selecting “copy”, then “paste”, and then changing the name)). So to create a branch all you have to do is type “svn cp http://svnRepos1/trunk http://svnRepos1/branches/branch13″. Terrific, right? No. Actually not so much. There are a few problems with this:
- Tags and branches are the same thing, which is nice because the one “cp” command covers everything. The problem is that there is no difference between a branch and tag.
- The “Subversion people” (I forget the exact name of the consortium that runs this thing) suggest that you use the following layout for your repository so that you can tell the difference:
- This layout works very well, we use it here. It makes it easy to tell branches from tags. Of course, it isn’t enforced at all. Again the headache this causes is largely to a person – namely me – writing support for a system in a different product. Also, because there’s no difference, and no enforcement of these directories, if you make a mistake putting one of these in the wrong place, nothing will detect it. You’re thinking, “But Dan, you can just move it, no wonder you’re writing a manifesto you’re one of those idiots in your basement with a tin foil hat”. But you’re wrong:
- I don’t have a basement.
- The real problem here is that unless you notice by accident nothing will tell you that you put the tag for your release version in the tags/ directory, and you will freak out when you try to check it out later and cannot find it.
- I’m not wearing a tin foil hat, I’m wearing a Cubs hat, and right now I’m pretty sure it makes more sense to wear a tin foil hat to block out signals from HAARP than it does to pull for the Cubs (motto:”Breaking hearts since before the triple bypass was invented”).
- This is a lie, I threw it in to try to be funny. My son lost my Cubs hat while we were on vacation this summer. I need to pick up a new one, along with another copy of Catcher in the Rye.
- It is very difficult to search for different versions of the same file across branches. As newer versions of Subversion have been released, it has become possible, but still not easy. SlickEdit’s Subversion History dialog does this.
Subversion’s merge command will merge another branch int0 your branch really well. It provides a –dry-run command (CVS could do a dry run for anything with the global -n option, which Subversion does not have). It works very well, except in a couple of mystery cases, where it does not work well at all. The key is to merge often. Here for example, development generally continues on the trunk. If you are “out on a branch” working on a large feature that touches a lot of files, you will be much happier if you merge with the trunk often. Eventually that feature branch will need to merge to the trunk, and that will be far easier if you continually merge the trunk into the feature branch.
Neither one of these provides a method to “cap” a branch. To make a branch read-only so that it can be checked out – but no longer checked into. This would be a good thing.
Finally, git and Mercurial provide an entirely different paradigm for version control – which means their branching works differently. Their fans will tell you it’s better… I won’t draw a conclusion yet.
I will leave you with a final thought: If there are plugins available to augment the functionality I’ve complained about – I don’t care. This is my manifesto, write your own. Just kidding – I’d love to hear about them, but the truth is that I have to write support for these products, so I have to handle the way they behave out of the box. So I can’t write support for history that shows branches across a file provided that a given plugin is installed.
I glanced at the preview – this is long, rambling, all text, no pictures, and spotty punctuation. I think it qualifies as a manifesto. Part 1 is a wrap.
P.S.: A colleague notes that I should mention that Clear Case did a fine job of branching over a decade ago.