Workflows
Code Freeze and Release Candidate Workflow
Use freeze boundaries and release-candidate iterations to stabilize release scope and expose risk before production rollout.
- Teams turning commands into repeatable routines
- Readers who need sequencing, branch, and sync discipline
- Basic understanding of fetch, pull, push, and branches
- A sense of how and why branches diverge
- Copying a workflow without checking branch state
- Choosing the wrong integration path on shared branches
Citations & Further Reading
- Git branch [Official]
- git-scm.com — Git tag [Official]
- Git revert [Official]
- Git cherry pick [Official]
What you will learn
- Understand the core purpose of Code Freeze and Release Candidate Workflow
- Master the basic usage and common options of Code Freeze and Release Candidate Workflow
- Use freeze boundaries and release-candidate iterations to stabilize release scope and expose risk before production rollout.
- Understand key concepts: What this workflow solves
- Know when to use this feature and when to avoid it
A code freeze is not “stop all coding.” It means restricting what can enter the release line. An RC is not final release; it is a testable candidate snapshot.
Start with a problem
Your team is collaborating on a project, branches are growing, merges are becoming more frequent — but there's no stable collaboration rhythm. Everyone syncs code their own way, and conflicts are piling up.
What this workflow solves
Without freeze boundaries, teams often face:
- moving release scope during final validation
- unclear defect attribution because baseline keeps changing
- repeated date slips with poor visibility
Freeze + RC creates a stable target surface for release verification.
Recommended sequence
1. Cut release branch from current main
git fetch origin
git switch main
git pull --ff-only origin main
git switch -c release/2026-04
2. Tag the first RC
git tag -a v2026.04.0-rc1 -m "Release candidate 1"
git push origin release/2026-04 --tags
3. Freeze admitted change types
Typical freeze-window admissions:
- blocker bug fixes
- mandatory release configuration fixes
- urgent security or compliance items
Everything else waits for the next iteration.
4. Produce new RC tags after each fix round
git switch release/2026-04
# merge or cherry-pick approved fixes
git tag -a v2026.04.0-rc2 -m "Release candidate 2"
git push origin release/2026-04 --tags
5. Publish final release tag after gates pass
git tag -a v2026.04.0 -m "Release 2026.04.0"
git push origin v2026.04.0
Two common ways to move fixes into RC
- commit directly on release branch (small urgent fix)
- fix on dedicated hotfix branch, then
cherry-pickinto release
Either is fine when every admitted fix remains traceable and intentional.
“Since we are here, let’s include this small improvement too” is a classic release destabilizer. Freeze periods prioritize predictability over opportunistic scope growth.
Common mistakes
Mistake 1: interpreting freeze as zero engineering activity
Freeze limits release-line intake, not all ongoing development.
Mistake 2: overwriting old RC tags
Create new RC tags per iteration to preserve verification history.
Mistake 3: fixing only on release line and never backporting to main
That creates long-term divergence between release and trunk.
- Define admitted change categories during freeze.
- Define pass gates for each RC round.
- Standardize RC tag naming.
- Assign ownership for backporting release fixes to main.
Good follow-up reads
Try it yourself
- Practice the code-freeze-and-release-candidate-workflow command in a test repository and observe state changes before and after
- Experiment with different options and compare the output differences
- Simulate a real scenario where you would need to use this, and walk through the full process
Further reading
Keep going on the same topic: