GitLab Flow compared with GitFlow and GitHub Flow Jump to heading
Branching model discussions usually present two options: GitFlow, with its develop branch and release ceremonies, and GitHub Flow, with one branch and continuous deployment. GitLab Flow sits between them and is often the right fit for teams that find GitFlow heavy but cannot deploy every merge straight to production. It keeps GitHub Flowโs single integration branch and short feature branches, then adds downstream branches only where reality demands them: environment branches when deployments are gated, release branches when several versions must be supported. Its central rule โ fixes go upstream first, then flow downstream โ prevents the most common drift problems of multi-branch models. This page compares the three and shows GitLab Flowโs two variants, within GitFlow vs GitHub Flow comparison.
When to use this approach Jump to heading
- GitHub Flow does not fit because production deploys need a gate, a schedule or approval.
- GitFlow feels heavy โ the
developbranch adds little โ but you need some structure beyondmain. - You are deciding on a model and want to compare all three on the same terms.
- You run environment promotion through Git, as in branch-per-environment GitOps patterns.
Step 1 โ See the three models side by side Jump to heading
The models differ in how many long-lived branches they have and what those branches mean.
Step 2 โ Environment branches: promote by merging downstream Jump to heading
In the environment variant, main is where features integrate, and branches named after environments represent what is deployed there. Promotion is a merge from upstream to downstream: main into staging, staging into production. Each environment branch deploys automatically when it changes.
# Promote what is on main to staging, then staging to production
git switch staging && git merge --ff-only origin/main && git push origin staging
# โฆ after verification on staging โฆ
git switch production && git merge --ff-only origin/staging && git push origin production Using fast-forward merges keeps each environment branch an exact prefix of the one upstream, so โwhat is in productionโ is always a commit that has been on main and on staging. The deploy side is covered in promoting a release from staging to production.
Step 3 โ Release branches: cut from main, fix upstream first Jump to heading
In the release variant, release branches are cut from main when a version ships, and receive only cherry-picked fixes. The rule that distinguishes GitLab Flow from GitFlowโs hotfix branches is upstream first: a fix is merged to main first, then cherry-picked to the release branches that need it.
git switch -c release/2.4 origin/main && git push -u origin release/2.4
# Later: a bug is found in 2.4
# 1. fix on main via a normal merge request
# 2. cherry-pick the merged fix to the release branch
git switch release/2.4 && git cherry-pick -x <fix-sha> && git push Fixing upstream first guarantees the fix is never lost in the next release, because the next release is cut from main, which already has it. Recording the cherry-pick with -x is covered in recording backports with cherry-pick -x.
Step 4 โ Enforce the direction of flow Jump to heading
Both variants depend on changes moving in one direction. Protect downstream branches so they accept only merges from upstream, and check periodically that nothing exists downstream that is missing upstream.
# Anything on production or a release branch that main does not have is a problem
for b in origin/production origin/release/2.4; do
echo "== $b"; git cherry -v origin/main "$b" | grep '^+' || echo "nothing missing upstream"
done # Merge requests into production may only come from staging
check-source:
rules: [ { if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "production"' } ]
script:
- '[ "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" = "staging" ] || { echo "promote via staging"; exit 1; }' Step 5 โ Choose a model by how you ship Jump to heading
The choice follows from two questions: how often can you deploy to production, and how many versions must you support at once?
Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
Is GitLab Flow specific to GitLab? Jump to heading
No. It is a branching model and works on any forge. GitLabโs documentation named and popularised it, and GitLabโs environment features fit it naturally.
Can environment branches and release branches be combined? Jump to heading
Yes: release branches for versions, and environment branches below each if deployments are gated. Keep the number of long-lived branches as small as your constraints allow โ each one is something that can drift.
Why not just use deploy tags instead of environment branches? Jump to heading
Many teams do: deploy a tag to an environment and record it, instead of keeping a branch per environment. Branches suit GitOps tools that watch a branch; tags suit pipeline-driven deploys. Both work with the upstream-first rule.
Related Jump to heading
- GitFlow vs GitHub Flow Comparison โ the parent topic.
- Running Releases with GitHub Flow โ the simplest of the three in practice.
- Setting Up GitFlow Branches and Protections โ the heaviest of the three, enforced.
- Environment & Deployment Branches โ environment branches in depth.