Branching Strategies Compared
Branching Strategies Compared
Choosing a branching strategy is one of the highest-leverage decisions a team makes. Get it right and releases become routine. Get it wrong and you spend your afternoons resolving merge conflicts, your evenings chasing regressions, and your weekends firefighting broken releases. This lesson maps the three dominant strategies — Git Flow, GitHub Flow, and Trunk-Based Development (TBD) — explains the engineering trade-offs of each, and shows you what top-tier companies actually deploy in production.
Git Flow: Structured Parallel Development
Introduced by Vincent Driessen in 2010, Git Flow defines a strict set of long-lived and short-lived branches. It was designed for software with explicit release cycles — think versioned libraries, mobile apps shipping to app stores, or enterprise software with quarterly releases.
Permanent branches: main (or master) always reflects production. develop accumulates completed features before a release.
Supporting branches (short-lived):
feature/*— branch fromdevelop, merge back todevelop.release/*— branch fromdevelopwhen the release is feature-complete; only bug fixes go in; merges to bothmain(tagged) anddevelop.hotfix/*— branch frommaindirectly; merges to bothmainanddevelop.
develop and release branches accumulate divergence. By the time release/2.4.0 merges, develop has moved on — and the reverse merge into develop is notoriously painful. Teams that adopted Git Flow in 2012 and never re-evaluated often spend 20–30% of engineering time on merge management. Even Driessen himself added a note to his original post recommending TBD for teams doing continuous delivery.
GitHub Flow: Simplicity for Continuous Delivery
GitHub Flow reduces the branching model to a single rule: main is always deployable. Every change — feature, fix, refactor — lives in a short-lived feature branch that is opened as a pull request, reviewed, and merged directly into main. Deployment happens immediately after merge, or on merge via CI/CD.
GitHub Flow works extremely well for SaaS products that ship multiple times per day. The PR is the unit of work: it carries the diff, the discussion, the CI results, and the deployment gate in one place.
v2 and v3 simultaneously (common for APIs or mobile SDKs), you are on your own. Teams often improvise release/v2 long-lived branches, effectively inventing a subset of Git Flow on top of GitHub Flow.
Trunk-Based Development: What High-Velocity Teams Actually Use
Trunk-Based Development is the strategy behind Google's monorepo (1 billion lines of code, one branch), Meta's internal tooling, and the majority of elite continuous-delivery organisations. The rule is even simpler than GitHub Flow: everyone commits directly to main (the trunk) at least once per day. Feature branches, when they exist at all, live for less than 24 hours.
TBD sounds chaotic to engineers who are used to long-lived branches, but it works because of three complementary practices:
- Feature flags — incomplete work ships behind a flag that is off in production. The next lesson covers this in depth.
- Comprehensive automated testing — the CI pipeline catches regressions before they reach
main; a broken build is an all-hands emergency. - Pair/mob programming or very tight PR review cycles — code is reviewed in real time or within 1–2 hours, not days.
What Big Tech Actually Uses
The empirical answer is: the industry has moved overwhelmingly toward Trunk-Based Development, with GitHub Flow as a pragmatic middle ground for smaller teams. Google, Meta, Microsoft (internal tooling), LinkedIn, and Etsy have all published engineering blog posts confirming TBD at scale. The DORA (DevOps Research and Assessment) report consistently finds that trunk-based development is a statistically significant predictor of elite software delivery performance — shorter lead times, higher deployment frequency, lower change failure rate.
The key enabler is not courage — it is engineering infrastructure: a fast, comprehensive CI pipeline (Google's is < 10 minutes for most targets), a mature feature-flag platform (LaunchDarkly, Unleash, Flipt, or homegrown), and a culture where a broken build is an immediate priority, not a post-standup topic.
Choosing the Right Strategy for Your Team
Apply these heuristics in order:
- Do you maintain multiple released versions simultaneously? If yes, Git Flow (or a simplified variant with long-lived
release/*branches on top of GitHub Flow) is probably necessary. - Can you deploy to production after every merge? If yes, start with GitHub Flow. Graduate to TBD once your test suite is comprehensive and review cycles are tight.
- Is your CI pipeline under 15 minutes end-to-end? TBD only works if the feedback loop is fast enough that developers do not batch up work to avoid waiting.
- Do you have feature flags? TBD without feature flags means incomplete features ship to users. If you cannot deploy flags, stay on GitHub Flow until you can.
develop into main, enforce PR-before-merge). That alone reduces merge pain by 70–80%. Then, once CI is solid and flags are in place, shorten branch lifetimes toward zero — that is TBD. Skipping straight from Git Flow to TBD usually fails because the prerequisite infrastructure is not yet there.
Release Branches: The One Git Flow Piece Worth Keeping
Even teams on GitHub Flow or TBD sometimes need release branches — when you are releasing a mobile app, an npm package, or a compiled binary where you cannot push a fix without a new store submission or CDN invalidation. In that case, a release/vX.Y branch cut from main at the release commit, used exclusively for cherry-picked critical fixes, is the right tool. Merge every fix back to main immediately using git cherry-pick (covered in Lesson 3).
The discipline rule: nothing lands on a release branch that has not already landed on main. Release branches are a delivery mechanism, not a development environment.
Common Failure Modes
- "GitHub Flow but branches live for two weeks" — this is not GitHub Flow, it is slow Git Flow without the structure. Long-lived branches defeat the entire model. Enforce a branch age limit in CI (e.g., fail PRs open longer than 3 days on stale base).
- Skipping the reverse merge in Git Flow — forgetting to merge
release/*back intodevelopmeans the next release is missing the very fixes you just shipped. Git Flow tooling automates this, but manual Git Flow workflows routinely skip it. - TBD without tests — committing to trunk daily without a comprehensive, fast test suite is just "we all edit the same branch and hope for the best." TBD requires tests as a hard prerequisite.
- Feature flags left on forever — flags accumulate as technical debt. At Netflix and Google, flags are given a scheduled removal date at creation time. Stale flags cause incidents (a flag left on that should have been removed has taken down production at multiple companies).