Software builds must be labeled with a unique, incrementing version number.
We follow "Semantic Versioning" because our industry as a whole has decided it's useful.
Version numbers should be predictable, so that (as developers) we know —and control— what version of the software we're working on.
Each build must produce a label that is unique enough that we can track a binary back to its build and the commit it was based on.
We use a centralized git workflow commonly known as mainline, feature branch or topic branch, with pull requests for code review prior to merging changes to the main branch.
Tags (with a specific prefix) on the default branch set a specific version for that commit, and builds from that commit will always have that version number.
We can generate a unique, predictable build number for any untagged build by starting from the most recent tagged version, and simply counting commits.
If the build is on a non-default branch, the branch name should be mapped to a pre-release identifier, and each commit increments a counter identifier, and we get a version like -feature.2. Once the code is merged to the default branch, the feature version number can be incremented automatically -- or we can tag the merge commit to change the version.
To make the process more predictable, we can use the commit message or the branch name to indicate an increment of a major or minor version number, so we don't have to wait to tag the merged commit. We can use:
- A prefix such as Conventional Commits uses, like
feat: - A trailer like
semver: featureorsemver: major - A prefix on the branch name like
feature/,fix/,release/
NOTE: For versions like windows assembly file versions that do not support semantic version -prerelease tags, we may use the revision number (the 4th digit) to carry the pre-release counter, or a build identifier. However, we still put the full semantic version into the "Informational Version" on the assembly.
Finally, if fixes need to be made to a released version (i.e. without releasing additional features), we can create a release/ branch from any tagged release, and use the same approach to increment a patch version number.
Below, there is an example diagram showing some changes being done following this mainline workflow with the same changes shown, for contrast, as they might be done in a modern Git-Flow or a staged release workflow.