Recommendations in SCM Branching Patterns in TFS
With the transition from Visual Source Safe (VSS) to Team Foundation Server (TFS) the power of branching in source code control becomes much more readily available. The increased ease of branching and merging bring with it the need to consider patterns in proper branching that fit how an organization works. Actually, sometimes it brings with it the need to consider how an organization may wish to work versus how it currently works. In either case, common patterns provide the best guidance on how to get the most out of Team Foundation Server’s branching support.
This document will provide guidance that is both generalized to software configuration management (SCM) and specific to TFS in a couple of patterns and also provide specific prescriptive guidance on a basic structure and practice in branching. Even the more prescriptive guidance should be viewed in a similar context as reference architecture.
A common branching model
Probably the most common branching model is one that cascades. In this model, as shown in Figure 1-1, each successive release of the code triggers a branch in order to build the next release of the code.
Figure 1-1. Cascading Branches
This model is easy to understand and seems to meet many of the needs for software development and support. It’s simply an intuitive way to branch code. As code is released, a branch is created from that release in order to be the seed for the next release. The ideas is that the tip of the code line that is the parent to the current development line is the latest stable release version. Ideally, this allows for production support to apply fixes by going back to the code line for a given release and making changes without affect on current development or issue that any undesired or untested new features will be added to the supported prior release. This model is commonly referred to as the Branch-by-Release model (Walrad and Strom 2002[iii]).
If we were to inventory the values of this cascading model we could easily come up with the following list:
- Developer friendly
- Clear code promotion
- Intuitive
- Ease of production support
- Isolated fixes from feature development
- Common base for V.Next development
A bit more investigation and thought into how this model is applied begins to bring out some weaknesses.
First, the Branch-by-Release model is not as developer friendly as it appears. The intuitiveness of the model begins to disappear when keeping up with the current development line becomes an issue. With every new release, the current development line moves and the developers must point their environment to a new repository location to go along with that shift (Wingerd and Seiwald 1998 [ii]) (Berczuk and Appleton 2003[i]). This is not the most developer friendly or intuitive development environment. When this pattern of moving current development lines is then taken and scaled out across multiple projects that a programmer may be working in it becomes even more confusing to know that the correct codeline is in use.
Additionally, any work in progress not destined for the current release in development is not able to be undertaken. This code-freeze, as it is common termed, reduces productivity and provides no location for developers not finalizing the programming on the current release to do their work on future features without the creation of private branches that must then be merged back into the new codeline. In reality, this is not a merge between a parent and child branch but between two differing branches.
Code freeze is a major impediment to parallel development. The alternative of private branching requires eventual baseless merging between the code in the private branch and the code in the eventual new development line. Many source code control systems as a matter of course allow such baseless merging through the support of merging between codelines that are not direct parent-child branches. Team Foundation Server is not one of these tools. The lack of inherent support for baseless merges is not an oversight but a design with best practices in mind. Baseless merges can still be accomplished but to TFS it is simply an edit of the target code and not represented as a merge. Anytime that a baseless merge is required the branching pattern used that lead to such a merge should be closely evaluated for better alternatives. A baseless merge is a red flag for SCM. Not only is it difficult, it challenges one of the expected values from the Branch by Release model – ‘Clear Code Promotion’. There is no longer a clear and direct lineage of a development lines code. This means there is no longer a clear lineage of the code that eventually reaches a given release, making it difficult to determine the origin of code for bug fixes and in which releases this code may be found.
Having been faced with either code freeze, which is not developer or development process friendly, or private branching and baseless merging which is not production support friendly or developer friendly a couple of the expected benefits of Branch by Release model are not realized. A common base for each success development line does not occur when a pseudo-sibling branch is merged into the line. Since there is no clear lineage for the seeming code the separation of fixes from feature development is broken when during post release (production support) multiple branches must be looked at to determine the origination of a bug and potentially how many locations this may have been merged into and in turn reintroduced. No one can easily tell how far back a defect may exist or a single point in which it was introduced.
Lastly, in the cascading model a bug fix approved for application to a given release must be propagated down through all the releases that came after it in order to merge that fix into the current development line. This introduces the likelihood of losing other approved bug fixes or introduction of new bugs in these later releases in which overlap occurs (Walrad and Strom 2002[iii]). Each of the subsequent releases codelines now must either run through the entire lifecycle of development for quality assurance and a new release generation or those codelines will differ in what exists in that codeline within the repository and what code is actually released for that codeline. In the former case, many potentially unneeded and undesired development cycles are used even for a small, approved code fix in a prior release. Or in the latter, a new build on a release codeline may produce differing results than the original. See Figure 1-2 for the example of the fix propagation.
Figure 1-2. Cascading model with post release bug fix
A preferred branching model
If a pattern that provides the benefits expected and desired originally in the Branch-by-Release model and provided additional value then it would be preferred. A model often referred to as mainline development (Berczuk and Appleton 2003 [i]) or Branch-by-Purpose (Walrad and Strom 2002[iii]).
In the mainline development pattern the current development line for the v.Next product does not shift. As a release of the product nears ready completion and the code reaches a feature complete status a branch from the mainline is made for that release. The difference between the Branch-by-Release and Branch-by-Reason is that even though a branch is being made for a release the branch is for the purpose of supporting that release not for becoming the trunk for the next release. The benefits behind this are as follows:
- Developer friendly
- No code freeze required
- Support for multiple groups working on multiple sub projects in parallel
- Ease of production support
- Production support has a specific branch in which feature development is truly isolated
- Common base for v.Next development or any features branches off of that
These benefits look a lot like the benefits desired in the cascading model but that were found to actually be lacking.
The goal in Branch-by-Purpose is to have a very specific purpose to branch that is expected to maintain it’s own existence for the purpose of a release or to wither away with the changes coming from that branch either merged into the single mainline or having been made in the mainline to begin with.
See Figure 1-3 for an example of the Branch-by-Purpose pattern.
Figure 1-3 Branch-by-Purpose
An inventory of some of the deficiencies found in the other pattern when compared to this pattern show a much improved model. The intuitiveness of a chosen pattern stays in tact in that all mainline development stays on the same codeline and all branches are descendants of that mainline either directly or indirectly. This allows for a clear code lineage for defect discovery and fix and a common location to which all fixes as needed merge back into- the mainline.
Work in progress during the preparation for of a release candidate for release does not inhibit developer work on the mainline for the v.Next version. This development can continue on the mainline versus a private branch and thus eliminates the need for a baseless merge. What is not demonstrated in the simple Figure 1-3 is that the v.Next Feature development could have start during the code chill section on what became Release 1.0. The only caveat being that those v.Next feature development started during code chill not be checked into the mainline until after the RC1 branch is created. If the developer working on the v.Next features during code chill needed to shift focus to QA fixes in prep for the RC1 branch then the mainline code for the v.Next could be placed on a shelveset and resumed in development when their prep for an RC1 branch was complete. Obviously, this provides maximum efficiency since there is no longer a Code Freeze in which no one can develop new code.
If a defect in the released version of the product is found the defect will be fixed in the QA branch that preceded that release and a new branch for the minor revision number will be created when the fix is approved, applied and a new minor release version is built. This also allows for a direct merge of any bug fixes from the QA line (RCx) of the release back into the mainline so that v.Next will not have the bug carried forward in it. It does not have to go through approval, application and release in all the other subsequent releases that may have occurred before it can be applied to the mainline.
This model is clearly an improvement over the cascading style shown originally. It is recommended that further study of the pattern be taken to understand the use of this pattern for applying long running activities and multiple parallel sub-projects that will all find their way back to the mainline but potentially in various releases (Walrad and Strom 2002[iii])
[i] Berczuk, Stephen P. with Brad Appleton. 2003. Software Configuration Management Patterns. Effective Teamwork, Practical Integration. Addison-Wesley.
[ii] Wingerd, Laura, and Christopher Seiwald. 1998. “High-Level Best Practices in Software Configuration Management.”
[iii] Walrad, Chuck and Darrel Strom. 2002. “The Importance of Branching Models in SCM.” IEEE Computing Practices. 0018-9162/02.
Technorati Tags: TFS, Team Foundation Server, Software Configuration Management, SCM, Branching