@@ -16,10 +16,23 @@ GitFlow is a branching model for Git that defines specific branch types and thei
1616=== Main Branches
1717
1818==== `main` Branch
19- * **Purpose**: Contains production-ready code
19+ * **Purpose**: Tracks the most recently published release — nothing more, nothing less. If it's
20+ on `main`, it has a tag and a Maven Central publish behind it.
2021* **Lifetime**: Permanent
21- * **Protection**: Direct commits are not allowed
22- * **Merges from**: `release/*` and `hotfix/*` branches only
22+ * **Protection**: Not currently enabled on GitHub (no required reviews/checks) — direct pushes are
23+ possible but should never happen outside the release step below. Enabling protection is a TODO,
24+ not a claim this document should make until it's actually turned on.
25+ * **Merges from**: `release/*` and `hotfix/*` branches only, as an explicit last step after that
26+ branch's tag has been pushed and its publish workflow has gone green — never before, and never
27+ automatically.
28+ * **Reset 2026-08-29 (SKaiNET#1198 thread)**: `main` had drifted ~1,800 commits behind `develop`
29+ (stuck at `0.2.0`) because the "merge release branch to `main`" step had been opened as a PR for
30+ every release since, and closed unmerged every time — `develop` was already the project's real
31+ default branch and the actual publish trigger (a pushed tag), so nothing *needed* `main` to be
32+ current, and it wasn't. Rather than reconcile ~1,800 commits of drift with no real value in the
33+ history itself, the old branch was renamed to `legacy` (its full history is still there, just
34+ not on `main` anymore) and a new `main` was created starting at the `0.51.0` tag. `main` before
35+ 0.51.0 lives at `legacy`, not in `main`'s own history.
2336
2437==== `develop` Branch
2538* **Purpose**: Integration branch for features under development
@@ -55,6 +68,10 @@ GitFlow is a branching model for Git that defines specific branch types and thei
5568
5669== Workflow Diagram
5770
71+ NOTE: This diagram shows the conceptual GitFlow shape (tag on `main` after merging the release
72+ branch in). SKaiNET's actual sequence tags the release branch's own commit *before* touching
73+ `main` — see <<_release_process,Release Process>> below for the real order and why.
74+
5875[mermaid]
5976ifdef::env-github[[source,mermaid]]
6077....
@@ -149,6 +166,12 @@ git branch -d feature/lstm-layers
149166
150167=== Release Process
151168
169+ This is the sequence actually used from 0.51.0 onward — it differs from a textbook GitFlow release
170+ in one important way: the tag lives on the *release branch's own commit*, independent of `main`,
171+ because the Maven Central publish workflow triggers on the tag push (`on: push: tags: '**'` in
172+ `.github/workflows/publish.yml`), not on anything landing on `main`. `main` is updated *after* a
173+ successful publish, as an explicit last step — never before, and never as a side effect of tagging.
174+
152175. Create a release branch from `develop`:
153176+
154177[source,bash]
@@ -158,31 +181,57 @@ git pull origin develop
158181git checkout -b release/1.2.0
159182----
160183
161- . Perform release preparations:
162- ** Update version numbers
163- ** Update documentation
164- ** Run final tests
165- ** Fix any release-blocking bugs
184+ . Perform release preparations, each as its own commit:
185+ ** `CHANGELOG.md`: full entry for the release
186+ ** `README.md`: short "What's New" highlights for *this* release only, pointing to `CHANGELOG.md`
187+ for history — do not let a "Previously, in ..." cascade accumulate here again
188+ ** `docs/antora.yml` (`skainet_version`) and any hardcoded dependency-coordinate snippets in the
189+ tutorials (grep for the previous version string across `docs/` and `README.md` to catch drift)
190+ ** `./gradlew generateKernelMatrix generateDocs` — run this *after* the version bump below, not
191+ before, or the regenerated docs stamp the wrong version
192+ ** `gradle.properties` (`VERSION_NAME`) — its own commit, last, matching `release: X.Y.Z`
193+ ** Run final tests; fix any release-blocking bugs on the branch
194+
195+ . Open a PR from the release branch to `develop` and merge it once CI is green — this is what
196+ actually brings the version bump back into the integration branch:
197+ +
198+ [source,bash]
199+ ----
200+ git push origin release/1.2.0
201+ gh pr create --base develop --head release/1.2.0 --title "Release 1.2.0"
202+ # wait for CI to go green, then merge
203+ ----
166204
167- . When ready, merge to `main`:
205+ . Tag the release branch's own `release: X.Y.Z` commit directly — not a commit on `main`, which
206+ doesn't have this release yet:
168207+
169208[source,bash]
170209----
171- git checkout main
172- git pull origin main
173- git merge --no-ff release/1.2.0
174- git tag -a v1.2.0 -m "Release version 1.2.0"
175- git push origin main --tags
210+ git tag -a 1.2.0 <release-commit-sha> -m "SKaiNET 1.2.0 — <headline>"
211+ git push origin 1.2.0
176212----
213+ +
214+ Pushing the tag triggers the publish workflow. **Wait for it to go green before the next step** —
215+ a red publish run means the tag exists but nothing actually shipped to Maven Central; do not treat
216+ tagging alone as "released."
177217
178- . Merge back to `develop`:
218+ . Once the publish workflow succeeds, merge `main` up to the release — the step every release
219+ before 0.51.0 skipped:
179220+
180221[source,bash]
181222----
182- git checkout develop
183- git merge --no-ff release/1.2.0
184- git push origin develop
185- git branch -d release/1.2.0
223+ git fetch origin
224+ git push origin <release-commit-sha>:refs/heads/main # fast-forward; main has no protection to route around
225+ ----
226+ +
227+ This is a manual step by design (see the `main` Branch section above) — not automated on publish
228+ success. Do it as part of closing out the release, not as an afterthought.
229+
230+ . Delete the release branch once both merges (into `develop` and `main`) are done:
231+ +
232+ [source,bash]
233+ ----
234+ git push origin --delete release/1.2.0
186235----
187236
188237=== Hotfix Process
@@ -257,16 +306,18 @@ git branch -d hotfix/1.2.1
257306* Run comprehensive test suite on `develop` and `main`
258307* Block merges if tests fail
259308
260- === Deployment Pipeline
261- * `main` branch deploys to production
262- * `develop` branch deploys to staging environment
263- * Feature branches deploy to development environment for testing
309+ === Publishing
310+ * A pushed tag (any branch, in practice always the `release/*` branch's own commit) is what
311+ triggers the Maven Central publish workflow — not landing on `main`.
312+ * `main` is a read-only mirror of "what's been published," updated manually after the fact (see
313+ the Release Process above); it has no deploy step of its own.
314+ * `develop` is where CI runs on every push/PR; there is no separate staging deploy.
264315
265316=== Branch Protection Rules
266- * Protect `main` and `develop` branches
267- * Require pull request reviews
268- * Require status checks to pass
269- * Require branches to be up to date before merging
317+ * `develop` is protected today: required `build-job` status check, no force-pushes, no deletions,
318+ enforced for admins too.
319+ * `main` is **not** currently protected — turning that on (required status checks at minimum) is
320+ a TODO, tracked so this document doesn't quietly drift from reality again.
270321
271322== Troubleshooting
272323
0 commit comments