As I’m revisiting Software Configuration Management Patterns and putting the patterns into a larger product team context, one of the things I realized is that a few of the patterns in SCM Patterns reflected the state of the world at the time: CI/CD was not common, nor was regular unit testing. Agile was just getting started, so “frequent” releases meant “monthly” or “quarterly.” This meant that we had patterns like Release Line and Release Prep Codeline. At the time a “Code Freeze” was a standard practice, though arguably not a pattern.
Given the current state of software development, “pre-release stabilization” doesn’t make sense as a Pattern. Release Line still does, if only as an emergency fallback. This post from August, 2009 describes the thinking behind those two patterns. While Release Prep Codeline is a sign of deep problems in your dev process, Release Line still makes sense.
When Brad Appleton and I wrote the SCM Patterns book we discussed two branching patterns related to releasing software: Release Line and Release Prep Codeline. The first is a pattern that allows teams to easily support released code. The second is a pattern to help you “stabilize” a codeline before a release while allowing parallel work for the next release to proceed. Too often, teams start Release Prep Codelines at the wrong time or for the wrong reasons without understanding the costs. Given the rate at which changes happen on agile codelines, the costs of creating a branch can be high if you do it for the wrong reasons.
If an ideal agile team had “shippable” software at the end of every iteration, a Release-Prep Code Line isn’t necessary. You just label your code at the end of the final sprint, and if you need to provide a fix that can’t be done from the mainline code, you start a release branch from that label.
Many teams can’t ship at the end of every sprint, so creating a Release Prep Codeline (branch) is useful. It avoids some poor alternatives, like having a code freeze. The branch can receive small changes to fix problems, and the mainline can add new features, refactor, and integrate the fixes from the release-prep branch.
As the time between creating the branch and releasing the project grows, the cost of merging changes between the branch and the Mainline increases because the source code diverges. This decreases the team's velocity and can increase the time to release.
A long interval between branching and release often happens for reasons like:
Quality issues. There are a lot of problems, so going from “feature complete” to “shippable” takes longer than expected.
“Code Freeze” happens before “Feature Freeze.” Not explicitly, but after the branch is created you identify new “must-have” features. This gets worse as the time between branch and ship increases.
So what is a team to do? Here are some suggestions:
Be agile and prioritize: If the release is the most important task, do that work on the Main Line and have everyone work on it. Don’t branch until you are ready to ship.
Add automated tests early. Try to be “ready to ship at the end of the sprint,” so you can avoid the costs of branching.
Don’t branch until you really are feature complete, and use the Release-Prep Branch only for a constrained set of fixes.
If you really need to start future work before the current release is ready to ship consider either:
Doing all work on the main line and isolate “future work” by architectural techniques. (Make new features plugins, for example).
Keeping the work that is highest priority on the main line, and create a Task Branch for the future activity. Those on the task branch are responsible for merging Main Line code into their branch, and when the release is done, the task branch get copied to the main line.
My tendency is to keep the highest-priority work on the main line as long as possible. The code you are about to release usually meets this criterion.
Technically, these are simple technical approaches to implement. Like all SCM issues, there are many non-technical issues to address. Product owners need to understand the costs of “working in parallel,” and an agile team is responsible for making sure that the product owners know these costs so that they can make the correct decisions about when to start a parallel work effort.