Git branching strategies that scale: from a solo repo to a team of fifty
Hi there. Quick question: how many branches are open in your repo right now, and how long has the oldest one been there? This article is about Git branching strategies, and how to pick the right one for your team size.
By the end of this article, you will know the four branching models that cover almost every project. You will have the commands for each one. And you will have a simple rule for telling which model fits the team you are on right now.
Most “Git is hard” stories are really “our branching strategy is hard” stories. The commands are the same everywhere: branch, merge, rebase. Three things differ between a calm repo and a messy one: how long branches live, who is allowed to push where, and when code becomes a release. Match those to your team’s size and release rhythm, and Git goes quiet. Get it wrong, and every Friday turns into a merge marathon.
This is a field guide to the four strategies that cover almost every project. It goes from a repo only you touch to a codebase fifty engineers share. It also gives you a way to tell which one you are actually in.
A branch is a pointer, not a copy
One idea sits under every strategy. A Git branch is a small, movable pointer to a commit. Creating one copies no files. Merging is usually cheap. The expensive part is divergence. The longer your branch and main grow apart, the more the world has changed under you. That makes the final merge harder.
Every strategy below is a different answer to one question: how do we keep divergence small?
Just you? Commit to main and tag releases
When you are the only contributor, process is pure cost. Nobody reviews your work, and nobody’s work collides with yours. So commit straight to main. Keep each commit a clear, single step. Mark releases with tags, so you can always answer “what shipped on the 1st?”
git add -A
git commit -m "Add offline cache for the transaction list"
# mark a release you can return to
git tag -a v1.4.0 -m "Offline transactions"
git push --follow-tags
Use a throwaway branch only when you want to try something risky without touching a working main. Think of it as a spike you might delete. Branch, explore, then either merge it or git branch -D it. No process, just a safety net.
Best for: Personal apps, prototypes, side projects, learning repos. Watch out: The day a second person joins is the day this stops being enough. Don’t let “it’s always been fine” outlive the solo phase.
2-8 people shipping continuously? GitHub Flow
This is the default I reach for on almost every team. There is exactly one long-lived branch, main, and it is always ready to deploy. Everything else is a short feature branch. It exists only long enough to open a pull request.
# always branch from an up-to-date main
git switch main
git pull --ff-only
git switch -c feat/payment-retry
# …commit your work…
git push -u origin feat/payment-retry
# open a PR, get a review, merge, delete the branch
The whole loop (branch, PR, review, merge, deploy) usually closes inside a day or two. main stays protected, so no direct pushes. CI runs on every PR. And because branches are small, the reviews are small too.
Best for: Most product teams, startups, apps with continuous or near-continuous delivery.
Many contributors, trunk must stay green? Trunk-based
As a team grows past roughly ten active committers, even short feature branches start to queue up and collide. Trunk-based development takes GitHub Flow one step further. Branches live hours, not days. Unfinished work hides behind feature flags instead of behind a long branch.
git switch -c quick/rename-balance-label
# one or two commits, merged the same day — often behind a flag
// the half-built feature ships dormant, toggled on later
if FeatureFlags.newTransferFlow {
NewTransferView()
} else {
LegacyTransferView()
}
The payoff is that everyone merges into a trunk that stays green and never drifts far. The cost is care. You need solid CI, fast tests, and a habit of using flags. This is how large, fast-moving teams avoid merge gridlock.
Best for: Larger teams, mature CI/CD, organisations practising continuous deployment. Watch out: Without feature flags and fast automated tests, “commit to trunk constantly” becomes “break trunk constantly.”
Versioned, scheduled releases? Git Flow (with eyes open)
Some projects do need to maintain several versions at once. Think desktop software, SDKs, or anything with a formal QA gate and a release calendar. Git Flow adds long-lived lanes for exactly this. It has an integration branch (develop), stabilisation branches (release/*), and emergency branches (hotfix/*) that patch production directly.
# integration happens on develop
git switch -c feature/loyalty-points develop
# stabilise a release without freezing develop
git switch -c release/2.0.0 develop
# patch production straight off main, then back-merge
git switch -c hotfix/login-crash main
Git Flow does the most, and it is the heaviest of the four. The extra branches buy you parallel release management. If you don’t need that, they only buy you longer-lived branches and more places for merges to go wrong. Most app teams do not need it.
Best for: Libraries, SDKs, enterprise software with scheduled, versioned, QA-gated releases.
Side-by-side
| Attribute | GitHub Flow | Trunk-Based | Git Flow |
|---|---|---|---|
| Team size | 2-8 | 8-50+ | Any, with formal releases |
| Branch lifetime | Hours to days | Hours | Days to weeks |
| Long-lived branches | main only | trunk only | main + develop |
| Release cadence | Continuous | Continuous deployment | Scheduled / versioned |
| CI requirement | Recommended | Essential + feature flags | Recommended |
| Complexity | Low | Medium (discipline) | High |
Which one are you in?
Pick your strategy
When two answers fit, choose the simpler one. You can always add process later; you rarely regret removing it.
Teams reach for heavy strategies too early. Start with the lightest model your scale allows. Only add branches when a specific pain forces your hand, such as parallel releases or a trunk you cannot protect.
A strategy decides where code lives. The day-to-day habits that make it work (commit messages, pull requests, reviews, and how a branch lands) are in the companion piece: Git workflow for teams.
Recap
The goal of this article was to help you pick a branching strategy that fits your team size and release rhythm. Here are the main points.
- A branch is a cheap pointer. The real cost is divergence, so keep branches short-lived and merge often.
- Solo? Commit to
mainand tag releases. - Small team shipping often? GitHub Flow. One protected
main, short feature branches, a PR for each. - Many committers? Trunk-based. Branches live hours, and unfinished work hides behind feature flags.
- Scheduled, versioned releases? Git Flow, but only if you really need parallel releases.
- When two answers fit, choose the simpler one.
I hope this writing helps you pick the right model for your repo. Thanks for reading.
Cited sources