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

Branching Model

We will utilize the following long-lived branches:

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 develop
git 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 develop
git 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 main
git 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 main
git 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 develop
git 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-feature
git 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

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.

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'

Release Workflow

The following steps outline the process for preparing and releasing a new version:

  1. Initiate Release Branch: When the develop branch has accumulated enough features for a new release (e.g., aiming for version X.Y.Z), a new branch named release-X.Y.Z is created from the develop branch.

    git checkout develop
    git checkout -b release-X.Y.Z
    git push origin release-X.Y.Z
    
    • The version number X.Y.Z should 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.
  2. Release Preparation: The release-X.Y.Z branch 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 PATCH version.
    • 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.
  3. 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 into main with 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
      
  4. Final Release (Merge into main): Once the release-X.Y.Z branch is stable and ready for the final release (potentially after one or more alpha/beta releases), it is merged into the main branch.

    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 the main branch history.
    • git tag: A tag with the final release version number (following SemVer) is created on the main branch to mark the exact point of the release.
  5. Sync main into develop: After the release branch has been merged into main, merge main back into develop to 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
    
  6. Cleanup: Once the release is complete and main has been synchronized into develop, the release-X.Y.Z branch 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:

  1. Create Hotfix Branch: A new branch named hotfix-X.Y.Z.A (incrementing the PATCH version according to SemVer) is created directly from the main branch at the release tag.

    git checkout main
    git checkout -b hotfix-X.Y.Z.A <release_tag>
    git push origin hotfix-X.Y.Z.A
    

    Replace <release_tag> with the tag of the problematic release (e.g., v1.0.0).

  2. Implement Hotfix: The necessary bug fixes are implemented and thoroughly tested on the hotfix-X.Y.Z.A branch.

  3. Merge into main: Once the hotfix is verified, it is merged back into the main branch.

    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
    
  4. Sync main into develop: After the hotfix has been merged into main, merge main back into develop to ensure that the fix is included in future releases.

    git checkout develop
    git merge --no-ff main
    git push origin develop
    
  5. Cleanup: The hotfix-X.Y.Z.A branch can then be deleted.

    git branch -d hotfix-X.Y.Z.A
    git push origin --delete hotfix-X.Y.Z.A
    

Benefits

Considerations

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.