GitFlow, GitHub Flow, or trunk-based development? Real teams have tried all three. Here's which one scales, which one quietly slows you down, and the branching strategy high-velocity teams like Netflix actually run.
You branch off main on Monday to build a feature. By Thursday you're three commits deep, two teammates have shipped to main underneath you, and when you finally open your pull request, GitHub greets you with 47 conflicting files. You spend Friday resolving conflicts in code you didn't write, terrified you'll silently undo someone else's fix. Nothing shipped. Everyone is grumpy.
That pain isn't a Git problem. It's a workflow problem. The branching strategy your team picks decides how often this Friday happens, and most teams pick one by accident, copy it from a blog post, and never revisit it. This article walks through the three workflows real teams use, when each one fits, and the one rule that matters more than which you choose.
Who this is for
Engineers on a team of 2–50 who share a repo and deploy more than once a month. If you've ever rebased a week-old branch, fought a `develop` vs `main` divergence, or wondered why "just merge it" is never that simple, this is for you. No deep Git internals required.
The real enemy: long-lived branches
Before comparing workflows, name the thing they're all fighting: branch lifetime. A branch is a bet that the world won't change while you're away. The longer it lives, the more main drifts out from under it, and the cost of merging back grows non-linearly. A one-day branch merges clean. A two-week branch is a conflict-resolution project of its own.
Every workflow that scales is, underneath, a strategy for keeping branches short-lived. Every workflow that hurts is one that quietly encourages them to live too long.
GitFlow, GitHub Flow, and trunk-based development are really three different answers to one question: how do we integrate work frequently without breaking the deployable branch? Keep that lens as we go, it's the difference that actually matters.
Two shapes of history, side by side
The cleanest way to feel the difference is to look at the shape of the commit history each model produces. On the left, trunk-based: one durable line (main) with tiny feature branches that touch down and merge back within a day or two. On the right, GitFlow: a permanent develop line parallel to main, with release and hotfix branches splitting off and rejoining on their own schedule.
Trunk-based (top): short-lived branches merge back into main constantly. GitFlow (bottom): a parallel develop line plus release and hotfix branches, integrating on a release cadence.
The top row reads as a straight line because integration is continuous, that's the point. The bottom row has more boxes because GitFlow has more *places work can hide*. Every extra long-lived line is another branch that can drift, another back-merge you can forget, another cherry-pick across branches when a hotfix needs to land in two places at once.
GitFlow vs GitHub Flow vs trunk-based, at a glance
Here's the whole comparison in one table. Read the downside column carefully, that's the one teams skip when they copy a workflow, and it's the one that bites six months later.
Workflow
Branches
Best for
Downside
GitFlow
main + develop (permanent); feature, release, hotfix (temporary)
Versioned/scheduled releases, mobile apps, desktop software, support branches
Heavy ceremony; develop drifts from main; hotfixes need cross-branch cherry-picks
GitHub Flow
main (permanent); short feature branches off main
Teams of 5–50 shipping to one environment several times a week, most SaaS
No built-in story for multiple release lines or supporting old versions
Trunk-based
main (trunk); branches live 1–2 days max, or commit straight to main
High-velocity teams with fast CI and feature flags, Netflix, Google, Meta
Demands fast CI, deep test coverage, and feature-flag infrastructure to be safe
The three mainstream Git workflows compared.
Watch out
If your team spends more time managing branches than shipping features, GitFlow is probably the wrong model for your release cadence. Ceremony is only worth it when you genuinely ship multiple versions on a schedule.
GitFlow: powerful, but often overkill
GitFlow defines two permanent branches (main and develop) and three kinds of temporary branch (feature, release, hotfix). It was designed for software with scheduled release cycles, mobile apps, versioned desktop software, anything where you support multiple released versions at once. For that world it's genuinely good: the release branch gives you a place to stabilize while new feature work continues on develop.
For web applications that deploy continuously, GitFlow adds ceremony without value. Merge conflicts get frequent, develop steadily diverges from main, and a production hotfix means cherry-picking the same change across branches so it doesn't vanish on the next release. Most teams reaching for GitFlow on a continuously-deployed SaaS would be faster with GitHub Flow.
Trunk-based development: what high-velocity teams actually do
Netflix, Google, Meta, and Spotify all run trunk-based development. Engineers commit directly to main (the trunk) or use very short-lived feature branches, one to two days, tops. Every commit to main triggers CI/CD. Feature flags control what users actually see, so incomplete features can ship to production but stay hidden behind a flag until they're ready.
This is fast, but it isn't free. Trunk-based development requires four things to be safe: a fast CI pipeline, comprehensive test coverage, feature-flag infrastructure, and a team culture comfortable with frequent small changes. Skip any of those and trunk-based stops being velocity and starts being a way to break production at high speed.
trunk-based-flow.sh
bash
# Short-lived branch, merged in under 2 days
git switch -c feat/payment-retry
# ...small, focused changes...
git add .
git commit -m "Add retry with backoff to payment client"
git push -u origin feat/payment-retry
# Open PR -> review -> CI green -> merge to main -> auto-deploy.# The feature ships dark behind a flag and flips on when it's ready.
GitHub Flow: the pragmatic middle ground
GitHub Flow is simpler than GitFlow and safer than pure trunk-based development. One permanent branch (main). Feature branches off main. A pull request is required to merge. You deploy from main. No develop, no release branches, no hotfix branches, just main and the short branches feeding it.
This works well for teams of 5–50 engineers shipping multiple times a week. It's the model most SaaS startups land on, and the one I recommend to most teams I mentor: it keeps branches short by design, gives you a review gate, and has almost no process overhead to forget.
The recommended PR flow, step by step
Whichever model you adopt, the day-to-day loop looks almost identical: branch small, push early, let CI gate the merge, and deploy from a green main. Here's that loop in order.
1
Branch off an up-to-date main
Pull first so you start from current reality, then cut a small, single-purpose branch. The narrower the scope, the shorter the branch lives.
2
Commit small and push early
Make focused commits and push within the first hour. An early push means CI runs against the team's latest main while your change is still tiny and easy to fix.
3
Open a pull request
Open the PR as soon as there's something to review, draft if it's not done. The PR is where review, CI checks, and the conversation live; it's not a final gate, it's the workspace.
4
Let CI run the gate
Tests, lint, type-check, and security scans run automatically. A required-status-check rule on main means nothing merges until the pipeline is green. CI is your safety net, not the reviewer's eyeballs.
5
Review, then merge to main
One approving review for most changes. Squash-merge to keep main's history readable, then delete the branch immediately so it can't quietly grow a second life.
6
Deploy from a green main
main is always deployable, so the merge can trigger the deploy automatically. If something's wrong, you roll forward or revert the single commit, not untangle a week of merged work.
pr-flow.sh
bash
# 1. Start from current main
git switch main
git pull --ff-only
# 2. Small, single-purpose branch
git switch -c fix/timeout-on-checkout
# 3. Commit small, push early
git commit -am "Raise checkout timeout to 30s"
git push -u origin fix/timeout-on-checkout
# 4. Open the PR (GitHub CLI), let CI run the gate
gh pr create --fill
# 5. After approval + green CI, squash-merge and clean up
gh pr merge --squash --delete-branch
What Netflix actually does
Netflix runs trunk-based development with a sophisticated feature-flag system (Archaius). Engineers merge to main multiple times a day, the CI pipeline runs in under ten minutes, deployment is automatic, and rollback is one command. The whole system is built around an unusual assumption: you will deploy broken code. The goal isn't to prevent every bad merge, it's to detect and revert it within minutes.
That only works on top of deep investment: comprehensive observability, a mature on-call culture, and automated rollback you trust at 3am. Don't copy the branching model without copying the safety net underneath it, trunk-based without fast detection is just fast breakage.
How to choose
Match the workflow to your team size, release cadence, and CI maturity, not to whatever a famous company tweeted about. The defaults below are a safe starting point.
Fewer than 5 engineers, ship continuously → GitHub Flow. Lowest overhead, hard to misuse.
5–50 engineers, multiple environments → GitHub Flow with environment promotion (deploy main to staging, promote to prod).
Large team, multiple release schedules or supported versions → GitFlow. The ceremony finally earns its keep.
High-velocity team with fast CI and feature flags → trunk-based development. Maximum speed, but only with the safety net in place.
Pro tip
Whichever model you choose, the one rule that beats all the others: **keep branches short-lived**. Long-lived branches → merge conflicts → slow teams → unhappy engineers. Everything else is a detail.
Common mistakes that cost hours
Letting branches live for weeks. The single biggest cause of merge hell. If a branch can't merge in two days, split the work smaller.
Adopting GitFlow for a continuously-deployed web app. You inherit develop/main drift and cross-branch hotfix cherry-picks for zero benefit.
Going trunk-based without feature flags or fast CI. You're not shipping faster, you're breaking production faster with no way to hide unfinished work.
Treating the PR as the only quality gate. Reviewers miss things; required CI checks (tests, lint, type-check, security scan) catch what humans don't.
Never deleting merged branches. Stale branches pile up, confuse teammates, and tempt someone to revive week-old work that's already drifted.
Long-running release branches that never get back-merged. A hotfix that lands on the release branch but not on main reappears as a regression next release.
Takeaways
The whole article in six lines
The real enemy isn't a workflow, it's **long-lived branches** that let main drift out from under you.
**GitFlow** fits scheduled, versioned releases; on continuously-deployed web apps it's mostly ceremony.
**GitHub Flow** (one main + short PR branches) is the pragmatic default for most 5–50-person teams.
**Trunk-based** is fastest, but only safe with fast CI, deep tests, and feature flags underneath it.
The PR loop is the same everywhere: branch small → push early → CI gates the merge → deploy from green main.
Copy Netflix's safety net (observability, fast rollback) before you copy their branching model.
Where to go next
Workflows are muscle memory, you learn them by doing, not reading. Practice the branching, rebasing, cherry-pick, and stash mechanics that every model relies on, then wire them into an automated pipeline so CI does the gating for you.
Git lab, branching, rebasing, cherry-pick, and stash in a real terminal. The mechanics every workflow above depends on.
CI/CD lab, build the pipeline that turns "CI green" from a slogan into an enforced merge gate.
DevOps Engineer path, where Git workflow, CI/CD, containers, and GitOps come together into how a team actually ships.
Want to go deeper?
This article covers concepts taught hands-on in the Cloud Engineer and DevOps career paths, with real terminal labs, production scenarios, and structured lessons.