Inside TFS

Branch By Release in TFS 2010 - Part 3

In our previous two columns, we have been discussing the Branch By Release pattern for version control configuration. (You can read Part 1 and Part 2 of the series.) This pattern is one of the easiest to implement, and works well depending on the application being developed. In this column, we are going to look at a more advanced version of this pattern. We will call this Branch By Release 2.0.

The Theory

Branch By Release 2.0 can also be referred to as Branch By Release -- Main Line. In this strategy, we have one main line of code, referred to as "Main", shown in Figure 1.


[Click on image for larger view.]
Figure 1.

Most development happens on the Main line of code. Each new major releases branches from this main line of code. As can be seen in Figure 1, Release 1.0 and Release 2.0 both branch from the Main line. Each minor release to a major release branches from the major release branch. In Figure 1, Release 1.1 is a child branch of Release 1.0.

Any changes, such as bug fixes, that are made on a branch or a sub-branch are forward-integrated back into the Main line. This allows those fixes to be integrated back into development, to make sure they are included in the next release branch.

The branching and merging that results from this pattern can become quite complex. Usually, when this pattern is implemented, a person is dedicated to the branching/merging process.

The Implementation
In the previous two articles, we saw how to implement the base Branch By Release pattern. It is easy to see how, using the same instructions, we can configure our Team Foundation Server 2010 version control system to implement the layout in Figure 1. However, there is one issue with implementing Branch By Release 2.0 in TFS that has to be explained and addressed. This is an issue that makes TFS a little different from other version control systems.

TFS's merging process relies on parent-child relationships between branches. Most other version control systems do not. TFS, by default, only knows how to perform a merge between parent/child branches, and vice versa. Using Figure 1 as an example, TFS knows how to merge information between the Main line and Release 1.0. And it knows how to merge between the Main line and the Release 2.0 branch.

However, out of the box, there is no way, using the IDE, to merge information between the Release 1.0 branch and the Release 2.0 branch. This is something you might want to do if, for example, you made a bug fix in the Release 1.0 branch, and wanted to move that fix into the Release 2.0 branch, but you can't use the Main line, because it is too far out of date.

The solution to merging items that are not directly branched from each other is to do a baseless merge. A baseless merge cannot be performed within the Visual Studio IDE. You have to do this from a command prompt. One thing to remember when you perform a baseless merge is that, because there is no relationship information between the two branches, you may have to perform more manual conflict resolutions than you would with a normal merge. The good news is that once you perform a baseless merge, TFS establishes a relationship between the files and folders involved in the merge, making future merges much easier.

We've recreated Figure 1 in Team Foundation Server 2010. Figure 2 shows a view of the Source Control Explorer folders, while Figure 3 shows the branch hierarchy of the different branches.


[Click on image for larger view.]
Figure 2.


[Click on image for larger view.]
Figure 3.

As you can see from Figure 3, there is no direct relationship between Release 1.1 and Release 2.0. As such, there is no direct way, in the Visual Studio IDE, to merge bug fixes from Release 1.1 back to the Release 2.0 branch. Instead, to merge between those two branches, we will need to perform a baseless merge from the command line.

To get started, open the Visual Studio 2010 Command Prompt by select Start | Microsoft Visual Studio 2010 | Visual Studio Tools | Visual Studio Command Prompt (2010). In the command prompt, run the following command to merge the changes from Release1.1 to the Release2.0:

tf.exe merge /recursive /baseless Release1.1 Release 2.0

(To see all the command line options available for manipulating version control, run "tf.exe /?"). In this example, there are merge conflicts that need to be resolved. Figure 4 shows an example of the Resolve Conflicts windows in TFS 2010.


[Click on image for larger view.]
Figure 4.

We have the option of keeping the source branch, keeping the target branch, or merging changes using the merge tool. We are going to keep the source branch changes, so we will click the button. Now that all the conflicts have been resolved, we can close the Resolve Conflicts window Take Source Branch Version, and are taken back to our command prompt.

As we have seen in previous articles, the merge process is still not complete. The merge has been performed in our local workspace, but we still need to check those changes in. This can be done using either the command prompt or Visual Studio.

After we have checked our changes in, if we select the changeset that was created for this baseless merge, and use the track changeset functionality discussed in the previous column, we can see the results of the baseless merge, shown in Figure 5.


[Click on image for larger view.]
Figure 5.

As you can see, there is a dotted line connecting the Release 1.1 and Release2.0 branches. This dotted line indicates that baseless merge has been performed between those two branches, and shows those two branches are now linked. All future merges can now be performed using the Visual Studio IDE.

Whether you choose the simple version of the Branch By Release pattern, or the slightly more complex version presented here, this pattern is a good place to start for those new to using version control, and for projects that have specific, discrete releases. In our next series of columns we will look at the Branch By Quality pattern, a popular branching pattern used as a basis for a variety of different ways to branch.

About the Author

Mickey Gousset spends his days as a principal consultant for Infront Consulting Group. Gousset is lead author of "Professional Application Lifecycle Management with Visual Studio 2012" (Wrox, 2012) and frequents the speaker circuit singing the praises of ALM and DevOps. He also blogs at ALM Rocks!. Gousset is one of the original Team System/ALM MVPs and has held the award since 2005.

comments powered by Disqus

Reader Comments:

Thu, Feb 24, 2011 Enrico Weigelt, metux IT service Thur/Germany

As Senior Architect I would fire anybody who does it that way from my team. Why ? Because it's _destructive_ and dangerous. #1: at the point where you merge mainline to release-2.0, you'll also get in all the other changes besides your bugfix, which were _not_ meant for the 2.0 release. An absolute NO-GO ! #2: an simple merge (eg. between release-1.1 and main) has quite high risk of conflicts, once both branches have diverged far enough, so you'll want to rebase first (maybe even incremental rebase). BTW: I fully agree BILL HEYS that mainline should be kept as stable as possible. That calls for topic branches, which alway have to be rebased to latest mainline (and also carefully tested) before merging in. One major point you should never forget: history is not just a technical detail, nor just an archive (to get back to later points some day), but also an important documentation (eg. auditing, QE, bisection, etc). Crisscross merges are _deadly_ poison here. greets.

Tue, Feb 22, 2011 Bill Heys

I would note, in your example, the Release 1.1 branch is branched from Release 1.0, and not directly from Main. Any merging from Release 1.1 to Main (as indicated by your arrow) would also be a baseless merge initially.

Tue, Feb 22, 2011 Bill Heys

I disagree with this approach. The Main branch (Main line) should be kept as stable as possible. At any time, it may be desirable to deploy code from Main to QA, or to release stable code to customers. For this reason, I recommend ALWAYS having a branch for development that is isolated from the Main branch.

Tue, Feb 22, 2011 Bill Heys

Merging from a child branch to a parent branch is NOT forward integration. In your example, "Any changes, such as bug fixes, that are made on a branch or a sub-branch are forward-integrated back into the Main line". This is an example of Reverse Integration (Child -> Parent)

Add Your Comments Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.