Versions are on the form:
x.y.z.[..]
Where these letters are numbers and there are arbitrarily many of them.
The first version is 1
. The next one is 2
. The only time when you
branch out to the next components is when you have the following case:
- You need to make a new version on top of
X
X+1
is already released
Then you make X.1
if that is not released. If X.1
is released you make
X.0.1
. Repeat until you have a version string that is not released.
For the release after X.Y
you make X.Y+1
if not taken (repeat).
Thus these versions form a partial order or a tree. Like:
5
|
4 2.2 2.1.1 2.1.0.1
| | / /
3 2.1 --------
| /
2
|
1
Motivation 1: simple updates
Sometimes I need to make a new version because of some simple
configuration changes. The configuration only matters to an installation
which is on version 3
:
5
|
4
|
3
|
2
|
1
I could make the configuration change in a new version 6
but then a
simple configuration deployment could in the worst case turn into a
database migration conflict (e.g.: more changes and thus more risk).
So I try to minimize risk by making a new version 3.1
:
5
|
4 3.1
| /
3
|
2
|
1
Then I can deploy the change with less risk.
Bug fixes on older versions
To reuse the tree from before: a bug affects versions 3
–latest. You make
a fix on top of 3
with the version 3.1
. Then you can merge that into
what becomes 4.1
, then into 5.1
, and finally into the main branch.
This is relevant if you need to support older versions of the software. If you only support the latest release then you might want to just fix the current
Addendum: keeping later versions synchronized
I want to stress that the main branch always gets the changes introduced on top of the older versions via cascading merges. That is just as true for the configuration case as for the bug fix case.