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 integratedmain- production-ready code, always stable and tagged with releasesfeature/*- individual feature development branchesrelease/*- 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.
-
Start the release
git flow release start X.Y.ZCreates a
release/X.Y.Zbranch fromdevelop. It is recommended to push the branch to remote. -
Prepare the release
- Final bug fixes
- Documentation updates
- Release notes preparation
-
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
- Merges the release branch to
-
Deploy to production
-
Tag-based hosting: deploy the tag directly
-
Branch-based hosting (e.g., Lagoon): manually sync to the
productionbranchgit push origin main:production
-
Expected release outcome
A successful release meets these criteria (they also ship in your project's
docs/releasing.md):
- Release branch exists as
release/X.Y.Zin the GitHub repository - Release tag exists as
X.Y.Zin the GitHub repository - The
HEADof themainbranch has theX.Y.Ztag - The hash of the
HEADof themainbranch exists in thedevelopbranch- This ensures everything pushed to
mainexists indevelop - Important if
mainhad any hotfixes not yet merged todevelop
- This ensures everything pushed to
- There are no open PRs in GitHub related to the release
- On branch-based hosting, the hash of the
HEADof theproductionbranch matches the hash of theHEADof themainbranch