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:
Things we would like to have:
Things we can live without:
If the above were your goals, you could then adopt a process like this:
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.