Version Control – Best Practices for Product Versioning and Branching in Long-Term Projects

branchingproduct-managementversion controlversioning

In a general sense, for long term projects that may have multiple releases during the products life cycle and require support of previous products, what is the best way to handle product versions and branching of the code base?

In a more specific sense, assume that proper distributed version control is in place (i.e. git) and that the teams are small to large in size and that developer may be working on multiple projects at once. The major issue that is being faced is that there is a contractual obligation to support old versions as they existed at the time which means that new development can not patch old code (Microsoft Office products could be an example of this, you only get patches for the feature year you own).

As a result the current product versioning is a touch convoluted as each main product has multiple dependencies, each with their own versions which may change between annual releases. Likewise, while each product has its own repository, most of the work is not done on the main source trunk but rather on a branch for that years product release with a new branch being made when the product is released so that it may be supported. This in turn means that getting a product's code base isn't a simple matter as one might think when using version control.

Best Answer

How much (and what kind of) structure you need depends a lot on what you want to be able to do. Figure out what you can't live without, what you want to have, and what you don't care about.

A good example set of decisions might be:

Things we can't live without:

  • be able to reconstruct any past release at any time
  • be able to maintain multiple supported major versions of the product at any time

Things we would like to have:

  • be able to perform ongoing major-feature development (for the next major release) without worrying about branch merges
  • be able to perform maintenance updates to past releases

Things we can live without:

  • automated backporting of changes from current work to past releases
  • never interrupt major feature development even for a few days or a week at at time

If the above were your goals, you could then adopt a process like this:

  1. Do all development work on the trunk of your VCS ("master" in git)
  2. When you are close to a major release, halt major feature development, and focus on system stability for a week or so
  3. When the trunk seems stable, create a branch for this major release
  4. Major feature development can now proceed on the trunk, while only bug fixes and release preparation are allowed on the branch
  5. However, all bug fixes to be made to the branch must first be tested on the trunk; this ensures that they will also be present in all future releases
  6. Create a (VCS) tag on the branch when you are ready to release; this tag can be used to recreate the release at any time, even after further work on the same branch
  7. Further maintenance releases to this major release (minor releases) can now be prepared on the branch; each will be tagged before release
  8. In the mean time, major feature development geared toward the next major release can continue on the trunk
  9. When you get close to that release, repeat the above steps, creating a new releases branch for that release. This allows you to have multiple major releases, each on their own branch, in supported status at the same time, with the ability to release separate minor releases against each.

This process won't answer all of your questions -- in particular, you will need a process in place to decide what fixes can be made to a release branch, and to ensure that bugs are not fixed on a release branch first (such fixes should always be tested on the trunk where possible). But it will give you a framework in which to make such decisions.