5. Release process
SO3 follows a branch-per-release model: development happens on main, and
every minor version gets a long-lived maintenance branch on which patch releases
are tagged. This keeps stable lines alive for backports while main moves on.
5.1. Overview
Three git objects work together, and GitHub surfaces them in different places:
Object |
Example |
Role |
|---|---|---|
|
|
Continuous development (the next, unreleased version). |
|
|
Long-lived maintenance line for a minor version. Patch fixes land here and are tagged. |
Tag |
|
Immutable point marking a delivered version. Release candidates use the
|
GitHub Release |
“SO3 v6.2.1” |
The release page (notes + assets), attached to a tag. Exactly one is
flagged Latest; |
5.2. Versioning
Versions follow semantic versioning vMAJOR.MINOR.PATCH:
MAJOR — breaking changes to the boot chain, ABI or on-disk formats.
MINOR — new features, backward compatible. Opens a new
release/vX.Ybranch.PATCH — bug fixes only, cut on an existing
release/vX.Ybranch.
Release candidates append -rc (optionally -rcN for successive
candidates), e.g. v6.3.0-rc.
5.3. Branch layout
main ──●──●──●──●──●──●───────► development (next version)
\
release/v6.2 ●──●──● maintenance line for 6.2.x
│ │ └─ v6.2.1 (tags live on the branch)
│ └──── v6.2.1-rc
└─────── v6.2.0
While a minor line has not diverged from main yet (no work started on the
next minor), its release/vX.Y branch and main may point at the same
commit — that is expected.
5.4. Which fixes go on a release branch?
Being a bug fix is not what sends a change to a release branch. main is
the continuous development line and carries both features and fixes as they
land; anything committed there simply ships in the next version. There are two
kinds of fix:
A fix for unreleased code, or one that can wait for the next version. Nothing special — it is an ordinary commit on
mainand ships in the nextvX.Y.0. Do not touch any release branch.A fix for an already-published version (e.g. a bug in
v6.2.1) that must ship before the next version. Only this case uses the patch-release procedure below: the fix lands onrelease/v6.2(taggedv6.2.2) and is also carried tomainso it is not lost at the next minor.
In other words, what sends a change to release/vX.Y is the need to patch a
live, already-released version — never the mere fact that it is a fix rather
than a feature.
5.5. Cutting a patch release (vX.Y.Z)
Patch fixes are committed on the release branch, then tagged. If a fix was
first merged into main, cherry-pick it onto the branch rather than
fast-forwarding.
git checkout release/v6.2
git cherry-pick <sha> # or commit the fix directly
# optional: publish a candidate first
git tag -a v6.2.1-rc -m "so3 v6.2.1-rc"
git push origin release/v6.2 v6.2.1-rc
gh release create v6.2.1-rc --title "SO3 v6.2.1-rc" \
--target release/v6.2 --prerelease --generate-notes
# final release
git tag -a v6.2.1 -m "so3 v6.2.1"
git push origin release/v6.2 v6.2.1
gh release create v6.2.1 --title "SO3 v6.2.1" \
--target release/v6.2 --latest --generate-notes
5.6. Cutting a new minor release (vX.Y.0)
When main is ready for a new minor version, branch off it, then tag:
git checkout main
git checkout -b release/v6.3
git push -u origin release/v6.3
git tag -a v6.3.0 -m "so3 v6.3.0"
git push origin v6.3.0
gh release create v6.3.0 --title "SO3 v6.3.0" \
--target release/v6.3 --latest --generate-notes
5.7. Rules of thumb
One
release/vX.Ybranch per minor, not per patch — patches are tags on the branch.Tags are immutable: never move or delete a published
vX.Y.Ztag. To correct a release, cut the next patch.Exactly one GitHub Release carries the Latest flag; every
-rcRelease is a pre-release so it never shadows the latest stable version.Once a
release/vX.Ybranch has diverged frommain, backport fixes withgit cherry-pick— do not fast-forward the branch ontomain.