Version Control – Risks of Having a Release Branch

branchingrelease-managementteam-foundation-serverversion control

Currently we manage our source code in a Microsoft Team Foundation Server project. We have the following branches:

  • Development
    • Feature 1
    • Feature 2
    • Etc.
  • Test

The process is that development is either done in the Development or a separate feature branch. As features and fixes are completed they are merged to the Test branch that is then deployed to a test environment. When we have a successful acceptance test of the Test branch we create a release from the test build and deploy it to production.

The reason for this approach is that we did not want to do a merge from Test to a Release branch before building and deploying to production since we would deploy different code than what was tested.

The downside of this approach is that often there are untested changes waiting in the test branch which delays delivery of hot fixes for critical bugs in production.

I see that it is common in the industry to merge to a Release branch and then deploy that. Is there a method that allows for easy hot fixes and not introduce the risk of untested differences when having a separate release branch?

Best Answer

...often there are untested changes waiting in the test branch which delays delivery of hot fixes for critical bugs in production.

Is there a method that allows for easy hot fixes and not introduce the risk of untested differences when having a separate release branch?

Yes, there is. The problem you've encountered is being caused by a bug in the workflow:

feature1 \
feature2 --> test --> release
hotfix1  /

As you've seen, if the features take time to test thoroughly, they act as a barrier for getting the hot fix through the pipeline. The takeaway there is that if you need to get a release out quickly, there shouldn't be anything in the release pipeline that isn't very close to being ready.

You can prevent that by moving the barrier ahead of the release part of the pipeline so that any delays in testing a change stay with the change:

feature1 --> feature1-test \
feature2 --> feature2-test --> release-test --> release
hotfix1  --> hotfix1-test  /

When a change is finished, it goes into a separate branch where it is tested. As long as testing is underway, all work on that change happens between the two branches. After testing has approved it, the tested code is merged into a pre-release testing branch where the full test battery is run once more before release. (In theory, this should be a formality and a non-event; I'll explain why later.) This means you can take a long as you want testing feature1 without delaying feature2 or the hotfix.

One important thing that's frequently overlooked is feedback. Whenever a release happens, that code needs to be merged into all branches where development and testing are being done. If hotfix1 breaks feature1, you want to find that out in feature1-test so it can be fixed there and won't stand in the way of a release containing hotfix2. If the feature integrates the released changes early, there should be fewer surprises in release-test. This arrangement allows you to treat hotfixes and features the same way from a development perspective and leaves the decision whether to subject a hotfix to the full battery of testing or fast-track it a matter of QA policy. The workflow is the same no matter what, and there isn't a quick branch/merge from/to the release branch.

NB: What's described here is a bit of an oversimplification because it doesn't take into account something in feature1 breaking something in feature2. This arrangement can be used in more-complex structures where release-test becomes integration-test and that feeds release-test.