This document describes the branch model, the purpose of each branch type, and how a change moves from a feature branch all the way to a stable release.
| Pattern | Purpose | Protected |
|---|---|---|
main |
Latest stable source of truth | ✅ Yes |
develop/X.Y |
Active feature development sink for version X.Y | ✅ Yes (PR only) |
support/X.Y |
Maintenance / backport development sink for version X.Y | ✅ Yes (PR only) |
feature/<id>-<description> |
Individual feature work, merged into develop/X.Y via PR |
❌ No |
bugfix/<id>-<description> |
Bug fix work, merged into support/X.Y via PR |
❌ No |
preview/X.Y |
Pre-release stabilization | ✅ Yes (1 approval required) |
release/X.Y |
Release stabilization | ✅ Yes (1 approval required) |
1. Feature work
└─ feature/123-my-feature
│
│ PR → develop/X.Y
│
2. Bug fix work
└─ bugfix/124-my-fix
│
│ PR → support/X.Y
│
3. Promote to preview
└─ promote-branch.yml (manual) → creates preview/X.Y + PR: develop/X.Y → preview/X.Y
│
│ PR open → [pull-request.yml]: compile, test, pack, benchmark (optional)
│ PR merged → [release.yml]: compile, test, pack, publish-NuGet (pre-release), GitHub release, docs
│
4. Promote to release
└─ promote-branch.yml (manual) → creates release/X.Y + PR: preview/X.Y → release/X.Y
│
│ PR open → [pull-request.yml]
│ PR merged → [release.yml]: publish-NuGet (stable), GitHub release, docs, creates support/X.Y (first time only)
│
5. Back-merge to main (automatic, highest version only)
└─ [release.yml] creates PR: release/X.Y → main (only when X.Y is the highest release branch)
│
│ PR merged → main is updated to the latest stable source
- Represents the latest stable release — always in sync with the highest released version.
- Direct pushes are not allowed (protected).
- Updated automatically via a PR created by
release.ymlwhenever the highestrelease/X.Ybranch publishes a stable release. - Serves as the baseline for version bumps: new development versions are derived from the state of
mainat the point the previous release left off. - The
build.ymlworkflow does not trigger onmainpushes (branch-ignore pattern excludespreview/**andrelease/**, andmaindoes not matchsrc/**changes by default in the context of the ignore rules — check the workflow for current specifics).
- Naming convention:
develop/<major>.<minor>(e.g.develop/1.2). - Protected: all changes are merged via pull request from
feature/**branches. - The
build.ymlCI pipeline runs on every push tosrc/. - When ready for stabilization, use
promote-branch.ymlto create apreview/X.Ybranch and open a PR.
- Naming convention:
support/<major>.<minor>(e.g.support/1.0). - Auto-created when the first stable release from
release/X.Yis published. - Protected: all changes are merged via pull request from
bugfix/**branches. - Can be promoted to
preview/X.Yfor a patch release.
- Short-lived branch for individual feature work (e.g.
feature/123-async-decoder). - Merged into the appropriate
develop/X.Yvia pull request. - Not protected — deleted after merging.
- Short-lived branch for bug fixes (e.g.
bugfix/124-decode-overflow). - Merged into the appropriate
support/X.Yvia pull request. - Not protected — deleted after merging.
- Created automatically by
promote-branch.yml. - Locked immediately: requires at least one PR approval before any merge.
- The
pull-request.ymlworkflow runs on every PR targeting this branch. - On merge,
release.ymlpublishes a pre-release NuGet package. - When all pre-release validation is done, promote to
release/X.Y.
- Created automatically by
promote-branch.ymlfrompreview/X.Y. - Locked immediately: requires at least one PR approval.
- On merge,
release.ymlpublishes a stable NuGet package and a GitHub release. - After the first stable release, a corresponding
support/X.Ybranch is auto-created. - When
X.Yis the highest release branch,release.ymlautomatically opens a PR to merge back intomain, keepingmainin sync with the latest stable state.
The X.Y in preview/X.Y and release/X.Y drives the version pipeline. See Versioning for details.
| GitHub Environment | Used by | NuGet feed |
|---|---|---|
Development |
build.yml, pull-request.yml |
Azure Artifacts |
Production |
release.yml |
NuGet.org |
preview/** and release/** branches are locked via the github/branch-protection/lock composite action when created. develop/X.Y and support/X.Y branches must be manually configured as protected in repository settings (PR required, no direct pushes). The github/branch-protection/unlock action temporarily removes protection when a workflow needs to push directly (e.g., bump-version.yml). Branches are always re-locked immediately after.