Git branching strategies: GitFlow, GitHub Flow, and trunk-based development
Compare the most common Git branching strategies — GitFlow, GitHub Flow, and trunk-based development — with concrete commands, branch structures, and a guide to choosing the right workflow for your team's release cadence and size.
On this page
- Why a branching strategy matters
- Trunk-based development
- How it works
- Requirements and trade-offs
- GitHub Flow
- Branch structure
- The workflow
- When GitHub Flow fits
- GitFlow
- Branch structure
- The workflow
- Strengths and weaknesses
- Comparing the three strategies
- How to choose the right strategy
- FAQ
- What is the difference between a branch and a fork?
- Should I use GitFlow or GitHub Flow?
- What is a feature flag and why does trunk-based development need it?
- How long should a feature branch live?
A Git branching strategy (also called a branching model or workflow) defines how a team names branches, how work moves between them, and how releases are produced. The strategy you choose directly affects how often you integrate, how much merge conflict you deal with, and how fast you can ship. This guide explains the three most widely used models — GitFlow, GitHub Flow, and trunk-based development — with concrete branch structures and commands, and helps you decide which fits your release cadence and team size.
Why a branching strategy matters
A branching strategy gives a team a shared, predictable way to work with Git. Instead of each developer inventing their own branch names and merge rules, a workflow standardizes three things: where new work starts, where finished work goes, and how a release is produced. The result is fewer accidental conflicts, clearer code review, and a main branch whose state you can trust.
Branches themselves are a mechanism of version control: a branch is an independent line of development that forks off the mainline. Git makes branching cheap because its commits are content-addressed snapshots, so creating and merging branches is fast even in large repositories. Because branches are cheap, teams can afford to isolate work — the strategic question is how much isolation you want and for how long.
There are two broad philosophies. Feature-branch workflows isolate each piece of work on its own branch and merge it back when complete. Trunk-based development keeps a single mainline and integrates changes almost continuously. Most teams use something between these two extremes.
Trunk-based development
Trunk-based development (TBD) is a version control management practice where developers integrate small, frequent changes into a single main branch — the trunk — rather than working on long-lived feature branches. It is closely tied to continuous integration and continuous delivery, because the trunk is expected to remain in a deployable state at all times.
How it works
In a pure trunk-based workflow, developers commit directly to the main branch, or use very short-lived branches that are merged within hours. The key constraints are:
- One long-lived branch (main, sometimes called
masterortrunk). - Changes are small and integrated frequently — often several times per day.
- Strong automated testing and builds guard the trunk, so integration is safe.
# Get the latest main and start work
git checkout main
git pull origin main
# Small change, committed directly to main
git add .
git commit -m "fix: handle empty response in API client"
# Or use a very short-lived branch that is merged the same day
git checkout -b fix/empty-response
git add .
git commit -m "fix: handle empty response in API client"
git checkout main
git merge fix/empty-response
Requirements and trade-offs
Trunk-based development works well for teams with fast release cycles, strong CI/CD, and a culture of small frequent commits. Because everything lands on one branch, it minimizes merge conflicts and keeps every developer working with the latest code. The trade-offs are real: it requires disciplined automated testing, and long-running or partially finished features need other mechanisms to stay safe — most commonly feature flags, which let you merge incomplete work behind a runtime switch that is off by default.
Trunk-based development is often associated with high-performing DevOps teams and is considered a foundation of continuous integration: if work sits on isolated branches for weeks before integration, you cannot call the process continuous integration, no matter how automated your builds are.
GitHub Flow
GitHub Flow is a simplified branching model built around a single main branch and short-lived feature branches, with pull requests (PRs) as the review and merge gate. It was designed for teams that deploy continuously and want a workflow that is easy to learn.
Branch structure
GitHub Flow uses just two kinds of branches:
- main — always deployable; everything is merged here and deployed from here.
- feature branches — created from
main, live for hours or days, and deleted after merge.
There is no separate develop branch and no release branches; every feature branch is treated the same way.
The workflow
# 1. Create a feature branch from the latest main
git checkout main
git pull origin main
git checkout -b feature/add-user-dashboard
# 2. Work and commit
git add .
git commit -m "feat: add user dashboard widget"
# 3. Push and open a pull request
git push -u origin feature/add-user-dashboard
# Open a PR on the host, request review, discuss changes
# 4. After approval, merge on the host, then clean up locally
git checkout main
git pull origin main
git branch -d feature/add-user-dashboard
The defining rules of GitHub Flow are that main is always in a deployable state, and that any merging into main happens through a reviewed pull request. Because there is no dedicated release branch, the pipeline that deploys from main must be trustworthy — the model works because every merged change is immediately deployable.
When GitHub Flow fits
GitHub Flow is a good fit for small to medium teams deploying web applications and SaaS continuously, and for open-source projects where random contributors open PRs. It is simple, keeps every merge reviewed, and ships fast. It is less well suited to projects that must maintain multiple simultaneously supported versions, because there is no built-in mechanism for release branches.
GitFlow
GitFlow is a branching model introduced by Vincent Driessen in 2010 that adds a permanent develop branch and a set of supporting branch types to handle releases and hotfixes explicitly. It is stricter than GitHub Flow and is designed for projects with scheduled releases and a formal release process.
Branch structure
GitFlow defines two long-lived branches plus three types of short-lived supporting branches:
- main — always reflects the state of production, tagged for each release.
- develop — the integration branch where features are merged; the most recent "in-development" code.
- feature/ (from develop)* — new functionality.
- release/ (from develop, merged to main and develop)* — preparing a release: only bug fixes, version bumps, and documentation.
- hotfix/ (from main, merged to main and develop)* — urgent fixes to production.
The workflow
# Start a feature from develop
git checkout develop
git checkout -b feature/user-auth
# ... work on the feature, commit ...
# Merge the finished feature back into develop
git checkout develop
git merge --no-ff feature/user-auth
git branch -d feature/user-auth
# Prepare a release: branch off develop
git checkout develop
git checkout -b release/2.0.0
# bump version, fix last-minute bugs
git checkout main
git merge --no-ff release/2.0.0
git tag -a v2.0.0 -m "Release 2.0.0"
git checkout develop
git merge --no-ff release/2.0.0
git branch -d release/2.0.0
# Hotfix straight to production
git checkout main
git checkout -b hotfix/emergency-fix
# fix the bug, commit
git checkout main
git merge --no-ff hotfix/emergency-fix
git tag -a v2.0.1 -m "Hotfix 2.0.1"
git checkout develop
git merge --no-ff hotfix/emergency-fix
Strengths and weaknesses
GitFlow's strength is structure: it separates stable production code from integration work, supports scheduled releases cleanly, and gives hotfixes a clear, low-risk path to production. It is a reasonable choice for larger teams and software that ships on a defined cadence and must maintain multiple versions.
The cost is complexity. For teams deploying continuously, GitFlow adds overhead — two permanent branches to keep in sync, release-branch bookkeeping, and merges in two directions for every release and hotfix. Many commentators, and Driessen himself in later reflections, have noted GitFlow is best suited to teams that do not deploy continuously and that the simpler continuous-delivery workflows fit most modern products better.
Comparing the three strategies
| Factor | GitFlow | GitHub Flow | Trunk-based |
|---|---|---|---|
| Long-lived branches | main + develop |
main only |
main only |
| Release model | Scheduled, formal | Continuous | Continuous |
| Feature branch lifetime | Days to weeks | Hours to days | Hours (or none) |
| CI/CD requirement | Optional | Important | Critical |
| Feature flags | Optional | Helpful | Often required |
| Merge conflicts | More common | Occasional | Rarely |
| Best for | Larger teams, versioned releases | Small-medium teams, SaaS, open source | High-velocity DevOps teams |
How to choose the right strategy
There is no single best workflow — the choice depends on your release cadence, team size, and deployment process.
- Choose GitFlow if you ship on a defined schedule, need a formal release and QA phase, or must maintain multiple supported versions of the same product.
- Choose GitHub Flow if you are a small or medium team deploying continuously from
mainand want a simple, PR-driven workflow with little ceremony. - Choose trunk-based development if you ship very frequently, have strong automated testing and CI/CD, and want to minimize merge conflicts — and you can pair it with feature flags to keep incomplete work out of the production path.
Whichever you pick, keep the workflow consistent, keep branches short-lived, and make the deploy pipeline trustworthy. The best strategy is the one your team can follow every day without friction.
FAQ
What is the difference between a branch and a fork?
A branch lives inside a repository and shares its history with the mainline. A fork is a copy of a whole repository on a hosting service, typically used when a contributor does not have write access to the original — changes travel back through pull requests. Branches are for isolating work within a project; forks are for collaborating across repositories.
Should I use GitFlow or GitHub Flow?
Use GitHub Flow if you deploy continuously, ship often, and want simplicity. Use GitFlow if you release on a schedule, need a formal release and QA phase, or must support multiple releases in parallel. For most modern web products, GitHub Flow or trunk-based development is the simpler, more appropriate choice.
What is a feature flag and why does trunk-based development need it?
A feature flag (or feature toggle) is a runtime switch that controls whether a piece of code is active. It lets you merge incomplete or risky work into the main branch behind a flag that is off by default, so the trunk stays deployable even while a feature is being built. Trunk-based development relies on flags because it has no long-lived feature branches to hide unfinished work.
How long should a feature branch live?
As a rule of thumb, a feature branch should live hours, not days, and rarely more than a couple of days. The longer a branch lives, the more it diverges from the mainline and the more merge conflicts and integration delays you accumulate. Trunk-based development keeps branches under a day; GitHub Flow keeps them short enough that a PR review can happen promptly.
Sources
- Wikipedia — Branching (version control) (en.wikipedia.org/wiki/Branching_(version_control)
- CC BY-SA 4.0)
- Wikipedia — GitFlow (en.wikipedia.org/wiki/GitFlow
- CC BY-SA 4.0)
- Wikipedia — Trunk-based development (en.wikipedia.org/wiki/Trunk-based_development
- CC BY-SA 4.0)
- Pro Git by Scott Chacon and Ben Straub (git-scm.com/book
- CC BY-NC-SA 3.0)
Share this guide
Related guides
- Git explained: how version control works
Git explained: what version control is, how Git stores history as content-addressed snapshots, why branches are cheap, and how Git and GitHub fit together.
- Open source licenses explained: MIT, Apache, and GPL compared
Open source licenses decide how others can use, modify, and distribute your code. This guide explains permissive licenses (MIT, Apache 2.0), copyleft licenses (GPL, AGPL), and how to choose the right one for your project.
- What is unit testing? How to write, structure, and run unit tests
Unit testing is the practice of testing the smallest testable parts of a program — functions, methods, or classes — in isolation. Learn what a unit test is, the arrange-act-assert structure, test doubles and mocking, the testing pyramid, and best practices for writing good unit tests.