How do I create bug fixes for EVERY version of a product EVER released

A customer asks the following question:

We are building factory machine. New machines are usually delivered with the current stable software version. We don't do regular updates because our customers prefer stability over new features. After reading the Rangers Branching Guide I have some questions. I understand the need for the main and the development branch, we had a similar thing using feature branches for feature development merging the finished feature into trunk/main.

But we must be able to create an independent bug fix for every version of our product we ever delivered. Customers are using our machines in a specific version perfectly optimized for their production process. If they find a bug or need a change they don't want to get any other bug fix or feature we added in the meantime.

Should we create a label for every released/delivered version of the software. Whenever a customer requests a fix for instance for version v6.5, I create a "Release v6.5.1" branch from main, fix the bug, create a release/label for v6.5.1.0 and reverse integrate the fix into main. If this customer needs another fix I can do the next fix on the same branch (v6.5.1.1). If a different user with the same base version needs a different fix I can create a "Release v6.5.2" branch.

Can I achieve this with one of your strategies. I didn't find a way, but maybe I'm missing something.”

What do you do when you no longer have version 6.5 in Main? Suppose you have released a new major version, Release 7.0?

One characteristic of labels in TFS to be aware of - they are not immutable. You can probably achieve your goals by labeling your code with each release (6.5, 6.5.1, etc.). But TFS will not prevent you from modifying the *contents* of a label after it is applied to a branch. This may cause problems with auditors who want the contents of release *locked down*. This is one reason we recommend creating a release branch for each release, and locking it down. Since you need to be able to apply bug fixes to any prior release, you would need perhaps two branches for each release. Branch Main -> Servicing and then branch Servicing -> Release each time you do a release.

Lets say you have just released version 6.5.0. You could branch Main to create a Servicing 6.5. Label the code Release 6.5.0, but also branch Servicing 6.5 to create Release 6.5.0 and lock it down.

Now you need to create a bug fix against Release 6.5.0 - apply this bug fix in the Servicing 6.5 branch and release it to your customer. Label the code in Servicing 6.5 as Release 6.5.1 but also Branch Servicing 6.5.0 (with the hot fix) to Release 6.5.1 and lock it down.

Now if you need to apply a second bug fix to Release 6.5.1 make this fix in Servicing 6.5 (which now has the code for 6.5.1 as latest version). Make the fix in Servicing 6.5. Label the code in Servicing 6.5 as Release 6.5.2 but also branch Servicing 6.5 to create Release 6.5.2 and lock it down.

Each time you get a new bug fix for Release 6.5.x the fix would be made in Servicing 6.5 branch, but you need to decide which sub-version of the code to apply the fix to. It could be either 6.5.0, 6.5.1, 6.5.2. You should have a label you can roll back to if you do not want the bug fix against the latest version.

Later when you release version 7.0.0, you would branch Main to Servicing 7.0 and then branch Servicing 7.0 to Release 7.0.0 and lock it down.

If you are concerned about the overhead of creating a new lock-down branch for major Release and each minor hot-fix you could probably get by with only creating Release branches for the major releases and not each hot fix. Nevertheless, read my latest blog to gain a better understanding of the actual overhead involved in creating a new branch:

Normally when you have a one-to-many relationship in a hierarchy (such as a branch hierarchy), you would make the *one* the parent and the *many* children of the parent. You might think you want to invert the relationship between the Release branch and the Servicing branch, since you have many possible bug fixes for a given release. But if you invert the relationship in this way: Branch Main to Release 6.5.0 and then branch Release 6.5.0 to Servicing 6.5.1 and later branch Release 6.5.0 to Servicing 6.5.2. But when you put the servicing branch(es) as a child of the Release branch, you cannot merge the bug fix back to Main without merging it into the Release branch first. You would no longer have a copy of Release 6.5.0 (as released) since you would have merged post-release bug fixes into it in order to get them all the way up to Main.