Release Branch Strategy
Introduction
This document outlines the release branch strategy adopted by our team. This strategy aims to ensure a stable and predictable release process, allowing for ongoing development while preparing for new releases and addressing critical issues in released versions. We will be adhering to Semantic Versioning for our releases and may utilize alpha and beta stages for early releases.
Strategy Name: Feature Branch Workflow with Release Branches
This strategy builds upon the foundation of a feature branch workflow and introduces dedicated release branches to stabilize code before deployment.
Core Principles
mainBranch Stability: Themainbranch will always reflect the currently deployed, production-ready code.- Isolated Release Preparation: Release preparation activities (bug fixes, documentation updates, final testing) will be isolated to dedicated release branches.
- Continuous Development: Active development of new features will continue on the
developbranch and feature branches while a release is being prepared. - Clear Release History: The branching strategy will provide a clear and traceable history of all releases.
- Semantic Versioning: All releases will follow the Semantic Versioning (SemVer) specification (MAJOR.MINOR.PATCH).
Branching Model
We will utilize the following long-lived branches:
main: The primary branch where the code of the current production release resides. Only release branches are merged intomain.develop: The integration branch for all new features. Developers create feature branches offdevelopand merge them back intodevelop.release-*: Temporary branches created fromdevelopwhen a new release cycle begins. These branches are used for final stabilization and preparation of a specific release. The naming convention should berelease-X.Y.Z(e.g.,release-1.0.0,release-1.1.0).
Merge Strategy Matrix
Use the following table to choose the merge strategy when moving changes between branches:
| Source Branch | Target Branch | Recommended Strategy | Example Commands | Reason |
|---|---|---|---|---|
feature/* |
develop |
Squash merge | git checkout developgit merge --squash feature/my-feature |
Keeps develop history clean while preserving the feature as one logical change. |
develop |
release-X.Y.Z |
Create branch from develop |
git checkout developgit checkout -b release-X.Y.Z |
Starts release stabilization from the current integrated development state. |
release-X.Y.Z |
main |
No-fast-forward merge | git checkout maingit merge --no-ff release-X.Y.Z |
Creates a visible release merge commit and keeps release history traceable. |
hotfix-X.Y.Z.A |
main |
No-fast-forward merge | git checkout maingit merge --no-ff hotfix-X.Y.Z.A |
Records the production hotfix as a distinct release event. |
main |
develop |
Required after main changes |
git checkout developgit merge --no-ff main |
Always sync main into develop after a release or hotfix is merged into main, so future development starts from the latest released code. |
develop |
feature/* |
Rebase or merge from develop |
git checkout feature/my-featuregit rebase develop |
Makes the feature branch appear based on the latest develop, helps resolve conflicts early, keeps PR diffs focused on feature changes, and makes the final squash merge cleaner. |
Merge Types with Graphs
The following examples show the main merge types used in this branching strategy.
No-Fast-Forward Merge
Use this for release, hotfix, and main to develop synchronization merges. It always creates a merge commit, even when Git could fast-forward.
Before:
main: A---B
\
release: C---D
Command:
git checkout main
git merge --no-ff release-X.Y.Z
After:
main: A---B-------M
\ /
release: C---D
Mis the merge commit.- This keeps the release or hotfix visible as a distinct event in history.
Squash Merge
Use this when merging a completed feature branch into develop. It combines all feature commits into one new commit on develop.
Before:
develop: A---B
\
feature: C---D---E
Command:
git checkout develop
git merge --squash feature/my-feature
git commit -m "Add my feature"
After:
develop: A---B---S (C---D---E is squashed into S)
feature branch is deleted after the squash commit is pushed.
Sis a single squashed commit containing the feature changes.- Delete the feature branch after the squash merge is complete.
Rebase
Use this to update a feature branch with the latest changes from develop before opening or updating a pull request.
Before:
develop: A---B---C
\
feature: D---E
Command:
git checkout feature/my-feature
git rebase develop
After:
develop: A---B---C
\
feature: D'---E'
D'andE'are rewritten versions of the feature commits.- Rebase is best for local or personal feature branches. Avoid rebasing shared branches unless the team agrees.
Release Workflow
The following steps outline the process for preparing and releasing a new version:
-
Initiate Release Branch: When the
developbranch has accumulated enough features for a new release (e.g., aiming for versionX.Y.Z), a new branch namedrelease-X.Y.Zis created from thedevelopbranch.git checkout develop git checkout -b release-X.Y.Z git push origin release-X.Y.Z- The version number
X.Y.Zshould follow Semantic Versioning principles:- MAJOR (X): Incremented for incompatible API changes.
- MINOR (Y): Incremented for adding functionality in a backwards-compatible manner.
- PATCH (Z): Incremented for backwards-compatible bug fixes.
- The version number
- Release Preparation: The
release-X.Y.Zbranch is dedicated to final release preparation tasks:- Bug Fixing: Only critical bug fixes related to the upcoming release should be applied to this branch. Avoid introducing new features. These fixes should typically result in an increment of the
PATCHversion. - Documentation Updates: Update release notes, user manuals, and any other relevant documentation.
- Final Testing: Perform thorough testing on this branch to ensure stability.
- Version Updates: Update version numbers in the codebase (e.g., in configuration files,
package.json, etc.). Ensure these reflect the final release version. - Communicate Changes: Ensure the team is aware of the ongoing release preparation and any changes being made to the release branch.
- Bug Fixing: Only critical bug fixes related to the upcoming release should be applied to this branch. Avoid introducing new features. These fixes should typically result in an increment of the
- Alpha and Beta Releases (Optional): For significant new features or changes, we may opt for alpha or beta releases from the
release-*branch:- Alpha Releases: Early pre-releases, often feature-incomplete and potentially unstable, used for initial feedback. Tagged with a pre-release identifier like
X.Y.Z-alpha.N. - Beta Releases: More stable pre-releases with most features implemented, used for wider testing. Tagged with a pre-release identifier like
X.Y.Z-beta.N. - To create an alpha or beta release, you would merge the
release-*branch intomainwith the appropriate tag:git checkout main git merge --no-ff release-X.Y.Z git tag -a X.Y.Z-alpha.1 -m "Alpha release version X.Y.Z-alpha.1" git push origin main --tags
- Alpha Releases: Early pre-releases, often feature-incomplete and potentially unstable, used for initial feedback. Tagged with a pre-release identifier like
-
Final Release (Merge into
main): Once therelease-X.Y.Zbranch is stable and ready for the final release (potentially after one or more alpha/beta releases), it is merged into themainbranch.git checkout main git merge --no-ff release-X.Y.Z git tag -a X.Y.Z -m "Release version X.Y.Z" git push origin main --tags--no-ff: This option ensures that a merge commit is always created, providing a clear record of the release merge in themainbranch history.git tag: A tag with the final release version number (following SemVer) is created on themainbranch to mark the exact point of the release.
-
Sync
mainintodevelop: After the release branch has been merged intomain, mergemainback intodevelopto ensure released changes, bug fixes, tags, and version updates are included in future development.git checkout develop git merge --no-ff main git push origin develop - Cleanup: Once the release is complete and
mainhas been synchronized intodevelop, therelease-X.Y.Zbranch can be deleted.git branch -d release-X.Y.Z git push origin --delete release-X.Y.Z
Hotfix Strategy
Critical bugs found in the production release (on the main branch) need to be addressed with a hotfix. The process is as follows:
-
Create Hotfix Branch: A new branch named
hotfix-X.Y.Z.A(incrementing thePATCHversion according to SemVer) is created directly from themainbranch at the release tag.git checkout main git checkout -b hotfix-X.Y.Z.A <release_tag> git push origin hotfix-X.Y.Z.AReplace
<release_tag>with the tag of the problematic release (e.g.,v1.0.0). -
Implement Hotfix: The necessary bug fixes are implemented and thoroughly tested on the
hotfix-X.Y.Z.Abranch. -
Merge into
main: Once the hotfix is verified, it is merged back into themainbranch.git checkout main git merge --no-ff hotfix-X.Y.Z.A git tag -a X.Y.Z.A -m "Hotfix release version X.Y.Z.A" git push origin main --tags -
Sync
mainintodevelop: After the hotfix has been merged intomain, mergemainback intodevelopto ensure that the fix is included in future releases.git checkout develop git merge --no-ff main git push origin develop -
Cleanup: The
hotfix-X.Y.Z.Abranch can then be deleted.git branch -d hotfix-X.Y.Z.A git push origin --delete hotfix-X.Y.Z.A
Benefits
- Stability of
main: Ensures that themainbranch always contains production-ready code. - Clear Separation of Concerns: Isolates release preparation from ongoing feature development.
- Organized Release Process: Provides a structured and repeatable process for releasing software.
- Traceable History: Offers a clear history of releases through merge commits and tags in the
mainbranch. - Efficient Hotfixes: Allows for quick and targeted fixes to production issues.
- Clear Versioning: Adherence to Semantic Versioning provides clarity on the nature and impact of each release.
- Early Feedback: Utilization of alpha and beta releases allows for early feedback and identification of potential issues.
Considerations
- Team Communication: Effective communication is crucial to ensure everyone understands the release process, the status of release branches, and the meaning of version numbers and pre-release identifiers.
- Branching Discipline: Strict adherence to the branching model is necessary for the strategy to be effective.
- Merge Conflicts: Be prepared to resolve merge conflicts when merging release or hotfix branches into
main, and when synchronizingmainback intodevelop. - Automation: Consider automating parts of the release process (e.g., tag creation, build and deployment triggers, version bumping) to improve efficiency.
- Strict Semantic Versioning: Ensure the team understands and follows the rules of Semantic Versioning when determining release versions.
- Alpha/Beta Management: Define clear criteria for when to use alpha and beta releases and how feedback will be handled during these stages.
Conclusion
By adopting this release branch strategy, incorporating Semantic Versioning and the potential use of alpha and beta releases, we aim to streamline our release process, improve the stability of our production code, gather early feedback, and provide clear communication about the nature of each release. Consistent adherence to these guidelines will contribute to a more efficient and reliable software delivery lifecycle.