For versioning, we use Semantic Versioning (major.minor.patch)
We increment the patch version for bugs/fixes
We increment the minor version for new functionality
We increment the major version for breaking changes (or to communicate to the user “big changes”)
For branching, we follow Trunk-Based Development, with some additions:
the development branch contains the upcoming/next release, while we branch for releases as close to the end of development as possible (usually around/after code freeze)
the release/x.y.z branch contains the code for that specific release
This allows us to patch/hotfix previous releases quickly, while working on riskier changes in isolation for the upcoming/next release.
...