Skip to main content

GitFlow versioning workflow

git-flow is a versioning workflow that separates development code from production code.

You keep a stable development branch (develop) and a production-ready branch (main), with dedicated branches for feature development, release preparation, and hotfixes.

develop ──► git flow release start X.Y.Z


release/X.Y.Z
(final fixes, release notes)


git flow release finish X.Y.Z

├──► merges into `main` and tags `X.Y.Z`
├──► merges back into `develop`


deploy the `X.Y.Z` tag
(or push `main` to `production` for branch-based hosting)

Branch structure

  • develop - development branch where features are integrated
  • main - production-ready code, always stable and tagged with releases
  • feature/* - individual feature development branches
  • release/* - release preparation branches (e.g., release/25.1.0)
  • hotfix/* - emergency fixes for production (e.g., hotfix/25.1.1)
production branch

Most hosting providers support deploying specific git tags directly. In this case, no separate production branch is needed - you tag releases on main and deploy those tags.

Some hosting providers (like Lagoon) require a git branch to deploy from, so tag-based deployments are not supported. In this case, you must create a production branch and sync code from main to production after each release.

While it's possible to automate copying main to production on tag creation via CI/CD, this automation was deliberately avoided to prevent accidental deployments to production without human oversight.

Release operations

Below are the typical steps to perform a release using git-flow. See the cheat sheet for a quick reference on git-flow commands.

  1. Start the release

    git flow release start X.Y.Z

    Creates a release/X.Y.Z branch from develop. It is recommended to push the branch to remote.

  2. Prepare the release

    • Final bug fixes
    • Documentation updates
    • Release notes preparation
  3. Finish the release

    git flow release finish X.Y.Z
    • Merges the release branch to main
    • Tags the release
    • Merges back to develop
    • Deletes the release branch
  4. Deploy to production

    • Tag-based hosting: deploy the tag directly

    • Branch-based hosting (e.g., Lagoon): manually sync to the production branch

      git push origin main:production

Expected release outcome

A successful release meets these criteria (they also ship in your project's docs/releasing.md):

  1. Release branch exists as release/X.Y.Z in the GitHub repository
  2. Release tag exists as X.Y.Z in the GitHub repository
  3. The HEAD of the main branch has the X.Y.Z tag
  4. The hash of the HEAD of the main branch exists in the develop branch
    • This ensures everything pushed to main exists in develop
    • Important if main had any hotfixes not yet merged to develop
  5. There are no open PRs in GitHub related to the release
  6. On branch-based hosting, the hash of the HEAD of the production branch matches the hash of the HEAD of the main branch