Git Flow
About
Git Flow is a branching model that standardizes how features, fixes, and releases are handled in Git-based projects. It introduces long-lived branches for stability (main
, develop
) and short-lived branches for isolated work (feature
, release
, hotfix
).
It is designed to help teams:
Work on multiple features or fixes in parallel.
Maintain stable production code.
Manage releases systematically.
Handle emergency fixes cleanly.
Introduced by Vincent Driessen, Git Flow is particularly suited to projects with scheduled releases, QA stages, and parallel development efforts.
Key Branches
Git Flow defines five main branch types:
main
Branch
main
BranchThe
main
branch (also calledmaster
in older repositories) is the production-ready branch.It contains the official release history of the project.
Every commit here is fully tested, stable, and ready to be deployed to production.
In many organizations, this branch is protected to prevent direct pushes.
Deployments and production rollbacks happen from
main
.Release tags (e.g.,
v1.0.0
,v2.3.5
) are created on this branch.CI/CD pipelines often trigger production deployment when a commit lands in
main
.Ensures traceability of what's running in production.
develop
Branch
develop
BranchServes as the integration branch for ongoing development work.
All completed
feature/*
branches are merged intodevelop
.When
develop
reaches a stable point (all planned features for a release are merged), it is used to create arelease/*
branch or directly merged intomain
if a release is ready.
Acts as the next release candidate base.
Continuous integration runs against
develop
to detect broken changes early.Helps separate unstable development code from stable production code.
Teams perform functional and regression testing on this branch before creating a release.
feature/*
Branches
feature/*
BranchesThese are short-lived branches used to develop individual features or enhancements.
Branches are created from
develop
.Once the work is complete and tested locally, the feature branch is merged back into
develop
.Naming follows a clear convention like
feature/user-auth
,feature/pdf-export
,feature/payment-gateway
.
Enables parallel development by different team members without conflicts.
Isolates incomplete or experimental code from the rest of the codebase.
Encourages incremental delivery by keeping each branch focused and small.
Helps enforce pull request reviews and code quality standards before integration.
release/*
Branches
release/*
BranchesUsed to prepare code for a production release.
Created from
develop
when all planned features for a version are ready.Only release-critical changes (bug fixes, final testing updates, version bumps) are made in this branch.
Once finalized, merged into both
main
anddevelop
.
Provides a stabilization window before releasing to production.
Allows teams to continue feature development on
develop
while QA happens onrelease/*
.Supports staging environments for user acceptance testing (UAT).
Prevents last-minute bugs from being directly introduced into production.
hotfix/*
Branches
hotfix/*
BranchesCreated to patch bugs found in the production environment.
Originates from
main
and is merged back into bothmain
anddevelop
to keep branches in sync.The fastest way to fix a production issue without waiting for the current development cycle to finish.
Named like
hotfix/memory-leak
,hotfix/1.2.1-crash-fix
.
Critical for rapid response to outages or high-priority defects.
Fixes can be released immediately, independent of current release or feature work.
Maintains a clean and traceable history of production hotfixes.
Keeps long-term and short-term workstreams decoupled.
How Git Flow Works ?
Starting a New Feature
Preparing a Release
Applying a Hotfix
Best Practices
1. Establish and Communicate our Branching Model Early
Before development starts, ensure all developers understand the purpose of
main
,develop
,feature/*
,release/*
, andhotfix/*
branches.Document it in the project's README, GitLab/GitHub Wiki, or internal engineering handbook.
2. Create Descriptive Feature Branch Names
Use clear, predictable patterns to name branches:
Avoid vague names like
feature/new-stuff
orbugfix/temp
.
3. Keep Feature Branches Short-Lived
Feature branches should be small, focused, and merged frequently.
Avoid long-running branches to minimize merge conflicts and divergence from
develop
.
4. Regularly Sync with develop
develop
Developers should rebase or merge
develop
into theirfeature/*
branches regularly.This avoids painful integration issues when finally merging back.
5. Enforce Pull Request Reviews
All merges into
develop
,release
, ormain
should go through a Merge Request/Pull Request.This enables peer review, automated checks (CI/CD), and code quality gates.
6. Don’t Commit Directly to develop
or main
develop
or main
Treat
develop
as our team-shared integration point, andmain
as your production environment.All work should go through
feature/*
,hotfix/*
, orrelease/*
.
7. Use release/*
to Finalize and Stabilize
release/*
to Finalize and StabilizeCreate a
release/*
branch when all features for a release are merged intodevelop
.Apply only critical bug fixes, documentation updates, or versioning here.
Prevent new features from creeping into a release late.
8. Merge release/*
into Both main
and develop
release/*
into Both main
and develop
After final testing and tagging on
release/*
, merge it into bothmain
anddevelop
.This ensures version bumps and fixes during release are also in the future development base.
9. Handle Hotfixes Through hotfix/*
hotfix/*
If an issue is found in production, immediately branch from
main
into ahotfix/*
.Once the fix is verified, merge it back into both
main
anddevelop
.
10. Tag Releases on main
main
Always tag production-ready commits (on
main
) with release versions:
Tags help identify what code is deployed and simplify rollbacks.
11. Automate CI/CD Based on Branches
Set up CI/CD pipelines to run tests and deploy from specific branches:
Run all tests on
develop
.Deploy to staging from
release/*
.Deploy to production from
main
.
12. Clean Up Merged Branches
After a branch is merged, delete it to keep your repo clean:
git push origin --delete feature/xyz
Automate this with merge request settings or CI jobs.
13. Avoid Overusing hotfix/*
hotfix/*
If we are frequently patching production with hotfixes, it's a sign of quality issues.
Improve regression testing and release QA.
14. Use .gitignore
and .gitattributes
Consistently
.gitignore
and .gitattributes
ConsistentlyStandardize file exclusions and attributes across the team to avoid inconsistent diffs and unnecessary files.
15. Document Common Git Flow Tasks
Create a cheat sheet for:
Starting a feature
Starting a release
Performing a hotfix
Tagging a release
Merging conventions
This saves time and avoids mistakes.
When to Use Git Flow and When Not ?
Criteria
Use Git Flow
Avoid Git Flow
Team Size
Medium to large teams (3+ devs)
Solo developers or very small teams
Release Frequency
Scheduled, versioned releases (e.g., weekly, monthly)
Continuous delivery or multiple daily releases
Release Process
Has distinct QA, UAT, and staging phases before production
Fast-paced, straight-to-prod after review/CI
Stability Requirements
Strict production stability needed
Low risk tolerance or MVP development
Hotfix Support
Needs ability to patch production independently
Hotfixes go through normal flow or are rare
Maintenance of Multiple Versions
Maintains older versions in production
Only latest version matters
Versioning Policy
Follows semantic versioning, releases are tagged
Versioning isn't tracked or is auto-generated by CI
Development Culture
Clear separation between dev, test, and release branches
Prefers simplicity and minimal branching
Branching Discipline
Team follows a strict process and naming conventions
Developers push frequently to one or two main branches
Tooling Setup
Has structured CI/CD pipelines for each branch type
Lightweight or manual deployments
Last updated
Was this helpful?