Branching strategies
Intermediate Core Git
Why this matters
A branching strategy is a team's answer to "where does work start and where does it end". You rarely choose one, but you always have to work inside one, and recognising which you are in tells you where to branch from and what to expect at merge time.
The four
GitHub Flow
One long-lived branch, main, which is always deployable. Work happens on short branches that merge back through a pull request and deploy from main.
Rules: main is always releasable; branch for anything; merge through review; deploy after merging.
Suits: web applications, teams that deploy often, most small and medium teams. It is the default assumption of both platforms' interfaces.
Costs: it assumes you can always ship what is on main, which needs decent automated tests and the ability to deploy easily.
GitLab Flow
GitHub Flow plus environment branches. main is still the line of development, and deploying means merging main into staging, then production; or, for versioned software, cutting release/* branches from main.
Rules: work merges into main; environments are branches downstream of main; nothing is committed to an environment branch directly.
Suits: teams with a staging environment, regulated release processes, or software that ships versions rather than deploying continuously.
Costs: more branches to keep track of, and a real risk of environment branches drifting if a fix is applied to one directly.
Git Flow
Two long-lived branches, main (what is released) and develop (what is next), plus feature/*, release/* and hotfix/* branches with defined merge routes between them.
Rules: features branch from develop; releases branch from develop and merge to both main and develop; hotfixes branch from main and merge to both.
Suits: installed software with several supported versions, long release cycles, formal QA phases.
Costs: the most machinery of the four. Its own author has since described it as unsuited to continuously delivered web applications, which is worth knowing when someone proposes it by default.
Trunk-based development
Everyone commits to main frequently, often several times a day. Branches exist but live hours rather than days, and unfinished work is hidden behind feature flags rather than kept on a branch.
Rules: integrate at least daily; keep changes small; rely on automated tests; use flags for anything incomplete.
Suits: experienced teams with strong test suites and a culture of small changes. It produces the fewest conflicts of any strategy, because nothing diverges for long.
Costs: it needs the tests and the flags. Without them it is just "everyone commits to main", which is how main gets broken twice a day.
What actually distinguishes them
Two questions separate all four:
| Question | GitHub Flow | GitLab Flow | Git Flow | Trunk-based |
|---|---|---|---|---|
| How many long-lived branches? | One | One plus environments | Two plus | One |
| How long does a branch live? | Days | Days | Days to weeks | Hours |
Everything else is detail. If you know the answers for your team, you know how to work there.
Finding out which one your team uses
Nobody will announce it. Four ways to read it off the repository:
CONTRIBUTING.md. If it exists, it usually says, and it is the first file to read in any repository (lesson 13.8).- The branch list. A
developbranch means Git Flow.stagingandproductionbranches mean GitLab Flow. Onlymainplus short-lived branches means GitHub Flow or trunk-based. - The merge history.
git log --graph --oneline -30shows what merges into what. Frequent tiny merges intomainsuggest trunk-based; arelease/*branch merging intomainsuggests Git Flow. - The protected branches. Whatever is protected is what the team considers precious, which is usually the answer.
$ git branch -r origin/HEAD -> origin/main
origin/docs/12-windows-install-steps
origin/main
origin/release/1.2That listing says: main plus a release branch, so releases are cut and supported, and work is short-lived. GitLab Flow's release variant, in other words.
How to do it
Two commands read a team's strategy in under a minute:
$ git branch -r
$ git log --graph --oneline -30The first shows the long-lived branches; the second shows how work gets into them.
The Source Control graph view shows the same shape visually, and the branch picker lists remote branches. The graph is the fastest way to see whether merges are frequent and small or rare and large.
The Log window with Branches in the sidebar is the best of the three for this: colour-coded lanes make a two-long-lived-branch model obvious at a glance.
Code → Branches shows all branches with their last activity, and Settings → Repository → Protected branches shows which ones the team treats as precious. Code → Compare revisions shows how far a release branch has diverged from main.
Branches in the repository, Insights → Network for the shape, and Settings → Rules for what is protected.
Common mistakes
- Assuming GitHub Flow everywhere. A
developbranch changes where your branch starts. - Branching from
mainin a Git Flow repository, where features come fromdevelop. - Proposing a strategy change in your first month. Learn why the current one exists first; there is usually a reason, and sometimes it is a good one.
- Committing directly to an environment branch, which makes it drift from
main. - Treating "trunk-based" as permission to skip review. It means small changes integrated often, not unreviewed ones.
Try it yourself
Goal: identify the strategy of three real repositories.
- Pick three public repositories you use, or three of your team's.
- For each, run
git branch -ron a clone, or read the branch list on the platform. - Look for
develop,staging,productionandrelease/*. - Read
CONTRIBUTING.mdif there is one, and see whether it agrees with your guess. - Write one sentence per repository saying which strategy it uses and where you would branch from.
Expected result: three sentences, each of which tells you exactly what to do on your first change in that repository.
Show solution
Step 4 is the check. When the documented process and the branch list disagree, the branch list is usually right and the document is out of date, which is itself worth knowing and worth a small merge request fixing the document.