Skip to content
Journal

Web Development · Developer Tools

Trunk-Based Development vs. Git Flow: Which Fits?

Trunk-based development wins on speed and CI/CD fit for most teams. Git Flow still earns its keep for versioned software. The verdict, by criterion.

Abhishek Gupta

Abhishek Gupta

9 min read

Two clay trees side by side, one with a single dark trunk and short branches, one with many colorful limbs

Sponsored

Share

Use trunk-based development if you deploy more than once a week, your CI suite finishes in single-digit minutes, and you’re willing to hide unfinished work behind a feature flag instead of a branch. Use Git Flow if you’re shipping versioned software with long support windows, a v2 and a v3 both taking security patches at the same time, or a release process that legally has to pass through a review stage outside engineering. A lot of web teams fall into the first bucket and still run the second workflow, mostly out of habit.

That’s not a hot take. It’s what Google’s DORA research group (DevOps Research and Assessment, the team behind the Accelerate book) found when they started actually measuring software delivery performance instead of arguing about it in standup. Trunk-based development, short-lived branches merged to main at least daily, shows up as one of the strongest technical predictors of elite delivery performance across every State of DevOps report DORA has published. Not a nice-to-have. A predictor, in the statistical sense, alongside loosely coupled architecture and fast automated testing.

The quick comparison

Trunk-based development means short-lived branches merged to main at least daily, backed by feature flags and fast CI. Git Flow means long-lived feature and release branches with staged merges. Trunk-based wins on integration speed and rollback speed; Git Flow wins on parallel version support and staged release review.

CriterionTrunk-basedGit Flow
Branch lifetimeHours (if branches exist at all)Days to weeks (feature), weeks to months (release)
Merge frequencyAt least daily, per DORA’s own benchmarkOn feature completion, often after code review queues
CI/CD fitBuilt for continuous deploymentBuilt for scheduled, batched releases
Code review cadenceSmall, fast PRs reviewed same-dayLarger PRs, reviewed in batches before merge to develop
Rollback methodFeature flag off, or revert one small commitHotfix branch cut from the last tagged release
Feature flags requiredYes, functionally mandatoryOptional, often unused
Best fitContinuously deployed web apps, SaaS productsMulti-version libraries, regulated release cycles

How this comparison is built

I’m not both-sides-ing this one. We maintain both models across different client codebases at CoderCops, and the failure modes are predictable enough that “it depends” stops being a useful answer past the first five minutes of a scoping call. The criteria below are the ones that actually decide whether a team is happy with its workflow six months in: how often integration hurts, whether CI can keep up, how fast a bug fix reaches production, and what happens the moment something breaks after a deploy. Pricing doesn’t apply here the way it would to a SaaS comparison, so I’ve skipped it. The cost that matters is engineer time lost to integration pain, and that shows up inside each section below.

Merge conflict frequency

Trunk-based wins, and not by a little. Here’s the part people get backwards: long-lived branches don’t cause merge conflicts by existing. They cause conflicts by delaying the moment a conflict gets discovered until it’s had weeks to compound. Two developers touching the same file on day one of a two-week feature branch would have a five-line conflict if they merged immediately. Wait two weeks, and that five-line conflict has grown alongside every other change either of them made in the meantime, because the branch drifted further from main with every day it stayed open.

DORA’s guidance is blunt about this: keep three or fewer active branches in the repository, and merge to trunk at least once a day. That’s not an arbitrary number. It’s the threshold past which conflict resolution stops being routine and starts eating whole afternoons.

CI/CD compatibility

This is where the two models actually diverge in architecture, not just process. Trunk-based development assumes CI runs on every commit to main and finishes fast enough that a broken build gets caught before three more commits land on top of it. Git Flow assumes CI runs mostly against release branches, with the expectation that develop can sit in a semi-broken state between releases because nobody’s shipping from it directly.

If your test suite takes 25 minutes, trunk-based development will hurt. Developers either wait 25 minutes per merge (nobody does this, they queue up commits instead, which defeats the point) or they stop trusting CI and start merging around it. Git Flow tolerates a slow suite better because it only really has to gate the release branch, not every commit. That’s a legitimate reason to stay on Git Flow, and it’s the honest answer to “why can’t we just switch,” not “our team isn’t disciplined enough.” Shrinking that number is usually a pipeline problem before it’s a workflow problem, and it’s worth fixing your CI runtime before deciding trunk-based isn’t for you.

Code review cadence

Trunk-based development forces small pull requests, because a PR that has to merge same-day can’t be 1,200 lines. That’s a genuine constraint, and it’s also a feature: research on code review effectiveness (Google and Microsoft both publish on this) shows defect detection drops sharply once a diff passes a few hundred lines. Reviewers start skimming. Git Flow’s longer branch lifetimes make it easy to accumulate a large diff before anyone looks at it, which is exactly the diff size research says reviewers are worst at.

We’ve written before about keeping Git workflow ceremony to a minimum for small teams, and the review-cadence argument is the strongest practical case for it: fast review turnaround only works when the thing being reviewed is small enough to review fast.

Release management

Here’s where Git Flow legitimately wins, and I want to be direct about it instead of hedging. If you maintain a v2.4 branch still under support while building v3.0, Git Flow’s release branches give you a clean place to cherry-pick security patches into both without tangling them together. Trunk-based development has no native answer to “we support two major versions in production simultaneously.” You’d bolt on release branches anyway, which is Git Flow with extra steps.

If you ship one thing, continuously, to one production environment, this advantage doesn’t apply to you. Most SaaS products and most web apps are exactly that: one live version, deployed from one place. That’s most of the corpus of teams reading this.

Rollback strategy

Trunk-based rolls forward. When something breaks, the fix is flipping a feature flag off (instant, no deploy) or reverting one small, recent commit (fast, because it’s small). Git Flow rolls backward: cut a hotfix branch from the last tag, patch it, merge to both main and develop, redeploy. That’s more steps and more places for the fix itself to introduce a new bug.

We cover the mechanics of this tradeoff in more depth in our blue-green and canary deployment guide, but the short version is that rollback speed correlates almost exactly with how small your unit of change is at the moment it breaks. Trunk-based development keeps that unit small by design. Git Flow’s release branches keep it deliberately large, batched, and reviewed, which is the right tradeoff exactly when you need a change frozen and audited before it ships, and the wrong one every other time.

Feature flags: the piece that makes trunk-based possible at all

Feature flags aren’t optional tooling here, they’re the mechanism. Without them, “merge everything to main daily” means either shipping half-finished features to users or not merging, and not merging is just a feature branch with extra guilt. A flag lets incomplete work sit in main, invisible, until it’s ready, which decouples “merged” from “released” entirely. That decoupling is the actual innovation, not the branching model.

Git Flow doesn’t need flags because it already has a place to hide unfinished work: the branch itself. That’s a real advantage for teams that haven’t built flag infrastructure yet, and it’s honestly a decent reason to stay on Git Flow for a few more months while you build it, rather than switching cold. OpenFeature and the current generation of flag tooling has made this cheaper to bolt on than it used to be, but “cheaper” isn’t “free,” and a team with zero flag infrastructure switching to trunk-based development overnight is trading one integration problem for a production-safety one.

Where each one actually wins in practice

A five-person team shipping a single SaaS product, deploying multiple times a week, with a CI suite under ten minutes: trunk-based, no real debate. The DORA data lines up with what we see client-side, and the switching cost is mostly cultural, not technical.

A team maintaining an open-source library with a supported v2 and an actively developed v3: Git Flow, or something close enough to it that renaming it wouldn’t change the outcome. You need parallel release lines and trunk-based development doesn’t model that natively.

A team new to CI discipline entirely, coming off manual QA and infrequent releases: neither, yet. Start with something closer to Git Flow’s structure while you build a fast, trustworthy test suite, then migrate to trunk-based once merges to main stop feeling risky. Jumping straight to trunk-based without that foundation just means broken commits reach production faster than they used to.

A regulated team where every release needs sign-off from someone outside engineering: Git Flow’s release branch gives that reviewer a stable, frozen artifact to actually look at. Trunk-based development doesn’t produce a natural checkpoint for that kind of review; you’d have to manufacture one, which is, again, Git Flow with extra steps.

The pattern across all four: trunk-based wins on integration speed and rollback speed every time, and Git Flow wins whenever the business, not the codebase, needs a slower, staged, reviewable release process. Pick based on which constraint is actually yours, not on which workflow your last team happened to use.

Frequently asked questions

What is trunk-based development?
Trunk-based development is a branching model where every developer merges small, frequent changes into a single shared branch (main, or trunk) at least once a day, instead of working in isolation on long-lived feature branches. Individual branches, when they exist at all, typically live for a few hours and merge the same day they're created.
Does trunk-based development work without feature flags?
Barely, and not for long. Without feature flags, the only way to keep unfinished work out of production is to not merge it, which recreates the long-lived branch problem trunk-based development exists to avoid. Feature flags let you merge incomplete code to main continuously while keeping it dark for users, which is what actually makes daily merging safe.
Is Git Flow dead?
No, but its default-choice status is. Git Flow was designed in 2010 for a world of scheduled desktop-software releases, and it's a poor fit for continuously deployed web apps, which is most of what gets built now. It's still the right call for teams maintaining multiple released versions in parallel, like library maintainers supporting a v2 and v3 simultaneously, or software with contractual, audited release cycles.
Can a small team really do trunk-based development without a platform team backing them up?
Yes, more easily than a large org, in some ways. The DORA prerequisites are fast CI (a suite that finishes in minutes, not fixing a specific test-runner) and feature flags, and both are achievable with off-the-shelf tools on a 3-8 person team. The scaling problem trunk-based development actually struggles with is thousands of engineers touching the same trunk simultaneously, which a small team doesn't have.
What breaks first if a team switches from Git Flow to trunk-based without preparing?
CI. Teams coming from Git Flow are used to running the full test suite only when a release branch is cut, so their suite is often slow and rarely exercised under load. Point that same suite at every commit to main and it either becomes the bottleneck or gets skipped under pressure, and a skipped suite on a trunk-based team means broken commits reach production.

Sources

Sponsored

Sponsored

Discussion

Join the conversation.

Comments are powered by GitHub Discussions. Sign in with your GitHub account to leave a comment.

Sponsored