Software process and the ilk

Thursday, March 01, 2007

Source Repository Layout

I spent a pleasant amount of time today looking into whether I want to replace my personal CVS version control with SVN. Subversion, you may know, is the much touted Open Source Solution to Version Control, burying CVS in features and so forth. This led to research about the truths of the matter (SVN looks good enough for me to give it a try - I do love my TortoiseCVS, but I'll try out TortoiseSVN), which led to the "standard" repository layout.

Now, I've been developing for long enough to recognize a "standard" repository by now, and I've seen enough to know that I haven't seen a standard. Done some work to improve the repositories I work with, both personally and on a team, but I hadn't given it much thought beyond that. Well, here it is:

/project
/project/trunk
/project/branches
/project/tags

What were you expecting, magic?

Failed Similes

Basically, this layout addresses life-cycles of projects. When a baby project is just being grown, of course we want protect it as much as possible. This means using source control. When something bad happens to the baby, we can just back up and restore the healthy child. If only real life were so simple!

When the baby becomes an adult, we typically want to release him into the wild. This "release" is something we want to hold on to. After all, people might come back and say the kid has some problem, like 4 fingers when he should have 5. We want to be able to fix those problems. On the other hand, we also want the kid to grow more, do more things. Basically, we have a problem. In real life, the kid can't leave and stay at the same time. Fortunately, software is not a kid, and the analogy holds no water. Like a prepositional phrase, it is out of here.

Like Elephants and Trees

What we want is to have two semi-related developments of the code: a release development, where we can address problems that users find and turn around with a patched version quickly, and an experimental version where we can try new things, throw out old things, and generally make a mess without worrying about John Q. Public.

Wait a second. The experimental version is kind of what the program was like before it was released, right? It didn't matter if this feature or that change broke everything, because Mr. Public hadn't seen anything yet. This experimental, playful (if you will) code state provides the core of everything else we wind up doing. It's where we say "what if" and see what happens. When good things happen, we turn it into a release. When bad things happen, we restore previous versions and move on. Since everything else stems from this, we'll call it the "trunk".

Of Streams and Rivulets

Release development typically results in a series of numbers. 1.0. 1.1. 1.2. 2.0. and so on. The 1.0 1.1 1.2 series is frequently a series of small changes. We found some bugs in the 1.0 code, so we fixed it and called that 1.1. We added a feature to that and released it, calling it 1.2 This is similar to the trunk, because we're taking a root and building on it. But it's different, too. We don't necessarily want these changes in the trunk, for one thing. (Of course, we might. That's what merging is for.) For another thing, it's not as playful. We need to have more certainty that we didn't break any of Mr. Public's expectations, no new bugs.

These are our "branches". By keeping them separate from the trunk, we can freely develop both at any time. We can even branch branches. Years later, when our trunk has wandered so far from our branches that we'd never know they were the same, we can still return to those branches to maintain and enhance them.

Frozen in Time

So far we have lots of growing things, quite the populous plant. Theoretically, we can get to every version of the code in the trunk and all the branches, and they can all grow independently of each other. But there's the practical side, too. We want to get to 1.1. Here we leave our forest discussion and invent a "tag".

A tag is a moment in code history. In development, there is a time when we say to each other: "Now. Now is when we release this code upon the world. Now is when it is ready." We nod knowingly. This is a big moment, and we may need to get back to it later. Here we tag the branch that is ready; we name it for the great out side; we call it "1.0". And we tag it, "1.0".

Later, we can come back to 1.0, fix those bugs, add those features, then tag and release "1.1". Tags are our ticket back to the past. Those four letters contain a flux capacitor, and we can see Doc's smile.

Are Magic

Now we know why the layout is standard. Well, it's not "standard", but it certainly seems to make sense. We know where our trunk development goes, we know where our branch development goes, and we can see where our tags go. Of course, the exact folder names and placement aren't quite as important as the ideas. We want to make our jobs as easy as possible; keeping these three concepts separate and clear does just that. So, when we see the layout:

/project
/project/trunk
/project/branches
/project/tags

we are seeing a little bit of magic.

No comments: