Trunk-Based Development vs Git Flow: Choosing the Right Branching Strategy for Teams in 2026

Posted on: 4/21/2026 1:15:08 PM

Your branching strategy determines how fast your team can ship code, the quality of code reviews, and the ability to rollback safely. Choosing the wrong Git model can turn your CI/CD pipeline into a merge conflict graveyard, block releases for weeks, and force developers to spend time resolving conflicts instead of building features.

This article provides a deep analysis of the two most popular models — Git Flow and Trunk-Based Development (TBD) — along with GitHub Flow, GitLab Flow, and data from DORA Research 2025–2026 to help you make the right decision for your team.

973× Elite teams deploy more frequently than Low performers (DORA)
6,570× Faster recovery time for Elite teams
< 1 day Lead time for changes of Elite performers
5 DORA Metrics (Rework Rate added in 2025)

What is Git Flow?

Git Flow was introduced by Vincent Driessen in 2010 and quickly became the most popular branching model. It clearly defines the role of each branch in the software development lifecycle.

gitGraph
    commit id: "init"
    branch develop
    checkout develop
    commit id: "setup"
    branch feature/login
    checkout feature/login
    commit id: "login-ui"
    commit id: "login-api"
    checkout develop
    merge feature/login id: "merge-login"
    branch release/1.0
    checkout release/1.0
    commit id: "bump-version"
    commit id: "fix-typo"
    checkout main
    merge release/1.0 id: "v1.0" tag: "v1.0"
    checkout develop
    merge release/1.0 id: "sync-develop"
    checkout main
    branch hotfix/1.0.1
    commit id: "critical-fix"
    checkout main
    merge hotfix/1.0.1 id: "v1.0.1" tag: "v1.0.1"
    checkout develop
    merge hotfix/1.0.1 id: "sync-hotfix"

Figure 1: Git Flow model with 5 branch types — main, develop, feature/*, release/*, hotfix/*

Branch Structure in Git Flow

BranchRoleLifetime
mainProduction code, each commit represents a releasePermanent
developIntegration branch, where all features mergePermanent
feature/*New feature developmentDays → weeks
release/*Release preparation, final bug fixesA few days
hotfix/*Emergency production fixesHours → 1 day

Advantages of Git Flow

  • Clear structure: Each branch has a specific purpose, easy to understand for new team members.
  • Parallel development: Multiple features developed simultaneously without affecting each other.
  • Controlled releases: Release process has a dedicated preparation step, suitable for scheduled releases (mobile apps, enterprise software).
  • Isolated hotfixes: Production fixes don't wait for in-progress features.

Disadvantages of Git Flow

  • Merge hell: Long-lived feature branches (weeks → months) accumulate large divergence, merging back to develop becomes a nightmare.
  • Slow feedback loop: Code review happens when the feature is "completely done" → massive PRs, overwhelmed reviewers.
  • Release bottleneck: Release branches add ceremony — version bumps, cherry-pick fixes, merging back to develop — easy to miss steps.
  • Poor CI/CD fit: The "deploy anytime" philosophy conflicts with long-running release branch processes.

⚠ A Confession from Git Flow's Creator

Vincent Driessen, the creator of Git Flow, added a note to his original blog post in 2020: "If your team is doing continuous delivery of software, I would suggest to adopt a much simpler workflow (like GitHub flow) instead of trying to shoehorn git-flow into your team." — Even the author recommends against Git Flow for continuous delivery.

What is Trunk-Based Development?

Trunk-Based Development (TBD) is a model where all developers commit directly to a single main branch (trunk/main), or use short-lived feature branches (lasting at most 1–2 days) that merge immediately. No develop branch, no long-running release branches.

gitGraph
    commit id: "feature-a"
    branch feat/search
    checkout feat/search
    commit id: "search-v1"
    checkout main
    merge feat/search id: "merge-search"
    commit id: "feature-b"
    commit id: "feature-c"
    branch feat/filter
    checkout feat/filter
    commit id: "filter-ui"
    checkout main
    merge feat/filter id: "merge-filter" tag: "auto-deploy"
    commit id: "feature-d"
    commit id: "feature-e" tag: "auto-deploy"

Figure 2: Trunk-Based Development — short-lived branches merge quickly, main is always deployable

Two TBD Variants

flowchart LR
    subgraph A["Direct Commits to Trunk"]
        A1["Developer A commit"] --> T1["main"]
        A2["Developer B commit"] --> T1
        A3["Developer C commit"] --> T1
    end
    subgraph B["Short-lived Feature Branches"]
        B1["Developer A"] --> FB1["feat/x
(lives < 2 days)"] FB1 --> T2["main"] B2["Developer B"] --> FB2["feat/y
(lives < 1 day)"] FB2 --> T2 end style T1 fill:#e94560,stroke:#fff,color:#fff style T2 fill:#e94560,stroke:#fff,color:#fff style FB1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style FB2 fill:#f8f9fa,stroke:#e94560,color:#2c3e50

Figure 3: Two variants — direct trunk commits (small teams) vs short-lived branches (larger teams needing code review)

Advantages of TBD

  • Minimal merge conflicts: Short-lived branches = less divergence = fewer conflicts.
  • Natural CI/CD: Main is always deployable, pipeline runs continuously on every commit.
  • Fast code review: Small PRs (tens to hundreds of lines) reviewed in 15–30 minutes instead of hours.
  • Fast feedback loop: Developers know about broken code in minutes rather than at the end of a sprint.
  • DORA-proven: DORA research shows TBD is a common trait of Elite performing teams.

Disadvantages of TBD

  • Requires strong automated testing: Without good tests, broken code affects the entire team immediately.
  • Feature flags necessary: Incomplete features must be hidden behind flags, adding management complexity.
  • Demands discipline: Developers must commit frequently, break tasks into small pieces, and avoid hoarding code for days.
  • Harder for junior-heavy teams: Requires understanding of CI/CD, testing, and feature flags.

GitHub Flow and GitLab Flow

Beyond Git Flow and TBD, there are two popular intermediate models:

flowchart TB
    subgraph GHF["GitHub Flow"]
        direction LR
        M1["main
(always deployable)"] F1["feature branch"] -->|PR + Review| M1 M1 -->|Deploy immediately| P1["Production"] end subgraph GLF["GitLab Flow"] direction LR M2["main"] F2["feature branch"] -->|MR + Review| M2 M2 --> E1["pre-production"] E1 --> E2["production"] end style M1 fill:#e94560,stroke:#fff,color:#fff style M2 fill:#e94560,stroke:#fff,color:#fff style P1 fill:#4CAF50,stroke:#fff,color:#fff style E2 fill:#4CAF50,stroke:#fff,color:#fff style E1 fill:#ff9800,stroke:#fff,color:#fff

Figure 4: GitHub Flow (simplest) vs GitLab Flow (adds environment branches)

ModelBranch TypesComplexityBest For
Git Flow5 (main, develop, feature, release, hotfix)HighScheduled releases, mobile apps, versioned software
GitHub Flow2 (main, feature)LowWeb apps, SaaS, continuous deployment
GitLab Flow3–4 (main, feature, environment branches)MediumNeeds staging/pre-prod environments
Trunk-Based1–2 (main, optional short-lived features)LowestMature teams, strong CI/CD, deploy on-demand

Detailed Comparison: Git Flow vs Trunk-Based Development

CriteriaGit FlowTrunk-Based Development
Branch lifetimeFeature branches: weeks → monthsShort-lived: hours → max 2 days
Merge frequencyWhen feature is "done"At least once per day
PR sizeHundreds → thousands of linesTens → hundreds of lines
Merge conflictsFrequent and complexRare and easy to resolve
Main branch stateOnly contains released codeAlways deployable
Release processRelease branch → QA → merge to mainDeploy from main anytime
HotfixSeparate hotfix branch, merge to both main + developFix directly on main, deploy immediately
Incomplete featuresLive on feature branch, not mergedMerged to main, hidden behind feature flags
CI/CD fitCI runs on develop, CD depends on release branchCI/CD runs continuously on main
DORA performanceMedium → Low performersHigh → Elite performers

Feature Flags — The Key to Trunk-Based Development

Feature flags (or feature toggles) allow toggling features on/off without redeployment. They are an essential component that makes TBD safe — developers can merge incomplete code to main without affecting users.

flowchart LR
    DEV["Developer merges
incomplete feature"] --> MAIN["main branch"] MAIN --> DEPLOY["Deploy to Production"] DEPLOY --> FF{"Feature Flag
ON / OFF?"} FF -->|ON for internal| BETA["Beta Users
see new feature"] FF -->|OFF for public| PROD["Public Users
see nothing"] FF -->|Gradual rollout| CANARY["5% → 25% → 100%"] style MAIN fill:#e94560,stroke:#fff,color:#fff style FF fill:#ff9800,stroke:#fff,color:#fff style BETA fill:#4CAF50,stroke:#fff,color:#fff style PROD fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style CANARY fill:#2196F3,stroke:#fff,color:#fff

Figure 5: Feature flags decouple deployment from release — deploy anytime, release when ready

Types of Feature Flags

TypePurposeLifetimeExample
Release FlagHide incomplete featuresShort (remove after release)NEW_CHECKOUT_FLOW
Experiment FlagA/B testingMediumPRICING_PAGE_V2
Ops FlagCircuit breaker, kill switchLong-termENABLE_ELASTICSEARCH
Permission FlagEntitlement, premium featuresPermanentADVANCED_ANALYTICS

✓ Golden Rule: Clean Up Feature Flags

Release flags are "planned technical debt" — after a feature is stable and rolled out to 100%, the flag and old code path must be removed. Teams should set expiration dates for each flag (e.g., 30 days after 100% rollout). Tools like LaunchDarkly, Flagsmith, or OpenFeature all support flag lifecycle management.

DORA Metrics and Branching Strategy

DORA (DevOps Research and Assessment) research from Google provides real data on the relationship between branching strategy and delivery performance. Since 2025, the DORA framework has expanded to include a 5th metric — Rework Rate — and transitioned from 4 tiers (Elite/High/Medium/Low) to 7 team archetypes based on both delivery performance and human factors.

flowchart TB
    subgraph DORA["5 DORA Metrics (2025+)"]
        DF["Deployment
Frequency"] LT["Lead Time
for Changes"] CFR["Change Failure
Rate"] MTTR["Mean Time
to Recovery"] RR["Rework Rate
(new in 2025)"] end subgraph ELITE["Elite Performers"] E1["Deploy: multiple times/day"] E2["Lead time: < 1 hour"] E3["Failure rate: 0-5%"] E4["Recovery: < 1 hour"] E5["Rework: < 10%"] end TBD["Trunk-Based
Development"] -->|"enables"| ELITE style TBD fill:#e94560,stroke:#fff,color:#fff style DF fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style LT fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style CFR fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style MTTR fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style RR fill:#f8f9fa,stroke:#e94560,color:#2c3e50

Figure 6: 5 DORA Metrics and Elite Performer benchmarks — TBD is the foundation for high performance

📊 Data from DORA Research

Moving from Medium to High performance requires adopting trunk-based development or short-lived feature branches. Elite teams share common traits: no long-lived feature branches, automated tests on every commit, small batch sizes, and a deployment pipeline fast and reliable enough to feel routine.

When to Choose Git Flow vs TBD?

flowchart TD
    START["Your Team"] --> Q1{"Deploy frequency?"}
    Q1 -->|"Daily /
multiple times/day"| TBD_REC["→ Trunk-Based Development"] Q1 -->|"Weekly /
monthly"| Q2{"Need to maintain
multiple versions?"} Q2 -->|Yes| GF_REC["→ Git Flow"] Q2 -->|No| Q3{"Team size?"} Q3 -->|"≤ 5 people"| GHF_REC["→ GitHub Flow"] Q3 -->|"> 5 people"| Q4{"Staging
environment?"} Q4 -->|Yes| GLF_REC["→ GitLab Flow"] Q4 -->|No| TBD_REC2["→ Trunk-Based
+ Feature Flags"] style TBD_REC fill:#4CAF50,stroke:#fff,color:#fff style TBD_REC2 fill:#4CAF50,stroke:#fff,color:#fff style GF_REC fill:#2196F3,stroke:#fff,color:#fff style GHF_REC fill:#ff9800,stroke:#fff,color:#fff style GLF_REC fill:#9C27B0,stroke:#fff,color:#fff style START fill:#e94560,stroke:#fff,color:#fff

Figure 7: Decision tree for choosing a branching strategy based on team and product characteristics

ScenarioRecommendationReason
SaaS web app, continuous deploymentTrunk-Based DevelopmentMain is always deployable, fast feedback
Mobile app (iOS/Android), App Store releasesGit Flow or GitLab FlowNeed release branches for each version, hotfixes for older versions
Open-source library, multiple versionsGit FlowMaintain multiple release lines (v1.x, v2.x)
Small startup, minimal processGitHub FlowSimplest, least overhead
Enterprise, compliance requirementsGitLab Flow + Environment branchesClear audit trail through environment promotion
Large team (>20 devs), monorepoTrunk-Based + Feature FlagsAvoid branch explosion and merge conflicts

Migrating from Git Flow to Trunk-Based Development

If your team currently uses Git Flow and wants to migrate to TBD, here's a phased roadmap instead of a "big bang" switch:

Phase 1: Shorten Feature Branches (Weeks 1–4)
Keep Git Flow but set a rule: feature branches cannot live longer than 3 days. Large features split into multiple small PRs. Start measuring cycle time from branch creation to merge.
Phase 2: Strengthen Automated Testing (Weeks 2–6)
Build a CI pipeline running on every PR: unit tests, integration tests, and linting. Target: 80%+ code coverage for critical paths. No merge if CI fails — this is the most important safety net.
Phase 3: Introduce Feature Flags (Weeks 4–8)
Deploy a feature flag system (OpenFeature, LaunchDarkly, Flagsmith, or custom). Start with 1–2 features using flags instead of long branches. Developers merge incomplete code to develop, hidden behind flags.
Phase 4: Eliminate the develop Branch (Weeks 6–10)
Merge develop into main, delete develop. Feature branches now branch from and merge to main. Release branches only used for hotfixing old versions (if needed). This is the decisive step transitioning to TBD.
Phase 5: Continuous Deployment (Weeks 8–12)
Every merge to main automatically deploys to staging → production (with feature flags controlling visibility). Monitor DORA metrics: deployment frequency, lead time, change failure rate, recovery time, rework rate.

⚠ Don't Skip Phase 2

Trunk-Based Development without strong automated testing will cause chaos. When all developers commit to the same branch, broken code affects the entire team immediately. A test suite is a prerequisite, not a nice-to-have.

Best Practices for Trunk-Based Development

1. Small Batch Size

Each PR should change fewer than 400 lines of code. Research from Google shows that PRs over 400 lines have significantly reduced review quality — reviewers start skimming instead of reading carefully. Break large features into multiple sequential PRs, each self-contained and deployable.

2. Pre-commit Checks

# .husky/pre-commit or CI pipeline
npm run lint
npm run type-check
npm run test:unit -- --changed

Run lint, type-check, and unit tests on changed code before pushing. Reduces CI feedback time from minutes to seconds.

3. Branch Protection Rules

# GitHub branch protection for main
- Require pull request reviews (≥ 1 approval)
- Require status checks to pass (CI pipeline)
- Require branches to be up to date
- Do NOT require linear history (allow merge commits)

4. Commit Message Convention

# Conventional Commits
feat(auth): add OAuth2 login flow
fix(cart): resolve race condition in quantity update
refactor(api): extract validation middleware
chore(deps): bump express to 4.21.0

Conventional Commits help auto-generate changelogs, semantic versioning, and make git logs easy to read.

5. Ship/Show/Ask Framework

TypeActionWhen to Use
ShipMerge directly, no review neededFix typos, update docs, bump dependencies
ShowMerge first, then open PR for team visibilitySmall refactors, obvious changes, confident about correctness
AskOpen PR, wait for review before mergingNew features, architecture changes, complex code

Real-World Adoption at Major Companies

Google Monorepo + TBD, ~80,000 commits/day in a single repo
Meta TBD for web, modified Git Flow for mobile (React Native)
Netflix TBD + Feature Flags, hundreds of deploys per day
Spotify TBD + Squad autonomy, each squad manages its own pipeline

Conclusion

No branching strategy is "correct" for every team. Git Flow still makes sense for software needing clear versioning and scheduled releases (mobile apps, SDKs, enterprise). But for web applications, SaaS, and any team wanting to deploy frequently, Trunk-Based Development combined with feature flags is the choice proven effective by DORA research.

The most important factor isn't which model you choose, but whether your team has strong enough automated testing to confidently merge code frequently, and a culture of trust where everyone commits small, reviews fast, and ships continuously.

References: