GitTrunk-Based Development

Trunk-Based Development

Trunk-Based Development (TBD) is the practice of integrating code into a single shared branch — called trunk or main — as frequently as possible, ideally multiple times per day. Rather than waiting for a feature to be complete before merging, developers commit small increments directly to trunk. Incomplete features are hidden behind feature flags so they do not affect end users until deliberately enabled. TBD is the workflow behind the continuous integration practices of Google, Facebook, Netflix, and most elite software engineering organisations.

The core model

Trunk-Based Development topology

Text
trunk (main):
  A ── B ── C ── D ── E ── F ── G ── H ──▶
  ↑    ↑    ↑    ↑    ↑    ↑    ↑    ↑
  │    │    │    │    │    │    │    │
Alice Bob  Bob Alice Bob Alice Alice Bob
(all committing small increments to trunk)

Short-lived branches (optional, < 1 day):
         ├── X ── Y ──┤  (Alice's tiny branch, merged same day)

Feature flags hide incomplete work:
  Feature "new-checkout" exists in code on trunk
  but is disabled in production via a config flag.
  Only enabled when fully tested and ready.
Two valid styles of TBD

Style

Description

Branch lifetime

Best for

Direct to trunk

Commit directly to main, no branches

N/A

Senior teams with strong CI/CD

Short-lived branches

Create a branch, merge within hours or 1 day max

< 1 day

Teams that prefer a PR review step

Feature flags: the key enabler

Feature flags (also called feature toggles) allow you to ship code that is not yet ready for users. The code lives in trunk and is continuously integrated, but a configuration switch keeps it invisible to end users until you decide to enable it. This decouples deployment (pushing code to production) from release (making a feature available to users).

Concept: feature flag in code

Bash
# Feature flag stored in environment config or a feature flag service
# (LaunchDarkly, Unleash, Flagsmith, etc.)

# In your code:
# if (featureFlags.isEnabled('new-checkout-flow')) {
#   return <NewCheckout />;
# }
# return <LegacyCheckout />;

# Developer commits the new-checkout code to trunk
# with the flag OFF (disabled for all users).
git add src/checkout/
git commit -m "feat: add new checkout flow [flag: new-checkout-flow=off]"
git push origin main

# CI/CD deploys to production — users see legacy checkout
# QA team enables the flag for the staging environment to test
# When ready: enable the flag for 1% of users → 10% → 100%

Simple feature flag implementation

Bash
# features.ts — a simple flag store
export const flags = {
  newCheckoutFlow: process.env.FEATURE_NEW_CHECKOUT === 'true',
  darkMode:        process.env.FEATURE_DARK_MODE === 'true',
  betaSearch:      process.env.FEATURE_BETA_SEARCH === 'true',
}

# In component:
# import { flags } from './features'
# const Checkout = flags.newCheckoutFlow ? NewCheckout : LegacyCheckout

# Environment variable in CI/CD pipeline (off by default):
# FEATURE_NEW_CHECKOUT=false  ← production
# FEATURE_NEW_CHECKOUT=true   ← staging / QA
Day-to-day workflow

TBD daily workflow (direct to trunk)

Bash
# Start of day: get latest trunk
git pull origin main

# Make a small, focused change
vim src/api/user.ts
# (write code, keep the change minimal — under 200 lines ideally)

# Run tests locally BEFORE committing
npm test
npm run lint

# Stage and commit
git add src/api/user.ts tests/user.test.ts
git commit -m "feat: add email verification to user registration"

# Pull again (someone may have pushed while you were coding)
git pull --rebase origin main

# Push immediately
git push origin main

TBD with short-lived branches (< 1 day)

Bash
# Create a branch (must be merged SAME DAY)
git switch -c feat/email-verification
# (< 1 day of work — keep it tiny)

git commit -m "feat: add email verification to user registration"
git push -u origin feat/email-verification

# Open PR for quick review
gh pr create --title "Add email verification" --body "..."
# (get approval within hours, not days)

# Merge
gh pr merge --squash --delete-branch
git switch main
git pull origin main
Continuous integration requirements

TBD only works safely when your CI pipeline is fast and reliable. Every commit to trunk must be automatically verified before anyone else can break on it.

Required CI pipeline for TBD

Text
Every commit to main triggers:
  1. Dependency installation (< 30 seconds)
  2. Unit tests (< 5 minutes)
  3. Integration tests (< 10 minutes)
  4. Static analysis / linting (< 2 minutes)
  5. Build (< 5 minutes)
  6. Deployment to staging (< 5 minutes)
  7. Smoke tests on staging (< 2 minutes)

Total: ideally under 15 minutes.
If CI takes > 30 minutes, TBD becomes painful.
Benefits of Trunk-Based Development
  • No merge hell — because everyone integrates continuously, large diverging branches never accumulate. Conflicts are tiny and resolved immediately.

  • True continuous integration — CI really runs on the integrated code, not just on isolated branches. You catch integration bugs immediately.

  • Fast feedback — developers know within minutes if their change broke something.

  • Smaller code reviews — changes are tiny (single commits or tiny PRs), making reviews faster and more thorough.

  • Simpler branching model — no develop, no release branches, no hotfix branches. One branch, one source of truth.

  • Deployments are boring — because each commit is small and verified, deployments carry minimal risk.

  • Lower WIP limit — fewer works-in-progress means less context switching and faster flow.

Challenges and prerequisites
TBD is not safe without a strong CI/CD pipeline
Trunk-Based Development requires fast, reliable automated tests and a deployment pipeline. Without these, broken commits reach production before anyone can stop them. Do not adopt TBD unless your CI/CD is in good shape.
  • Fast test suite required — if tests take 40 minutes, no one will run them locally before pushing.

  • High test coverage required — bugs hidden by feature flags still land in production code. Tests must catch them.

  • Team discipline required — everyone must commit small, self-contained increments. Large changes need to be broken down.

  • Feature flag infrastructure required — for any feature that takes more than a day to build.

  • Strong code review culture — even without formal PRs, code quality must be maintained through other means (pair programming, post-commit review).

TBD vs feature branch workflows

Dimension

Trunk-Based

Feature Branch

Branch lifetime

Hours or none

Days to weeks

Merge frequency

Multiple times per day

When feature is complete

Integration testing

Continuous on trunk

At PR review time

Merge conflicts

Rare (tiny, frequent merges)

Common (large, infrequent merges)

Feature isolation

Feature flags

Separate branches

Code review

Post-commit or tiny PRs

Pre-merge via PR

Required discipline

Very high

Moderate

Required CI/CD

Excellent

Good

Used by

Google, Facebook, Netflix

Most teams

Who uses Trunk-Based Development
  • Google — tens of thousands of engineers commit to a single monorepo trunk. This is perhaps the largest TBD implementation in the world.

  • Facebook/Meta — similar monorepo approach with sophisticated automated testing and feature flags.

  • Netflix — TBD with extensive CI/CD and canary deployments.

  • Etsy — famously championed continuous deployment from a shared trunk.

  • High-performing DevOps organisations — DORA research consistently finds that elite performers use trunk-based development.

Release branches are still allowed in TBD for versioned software
Trunk-Based Development does not prohibit release branches — it specifically allows short-lived release branches for teams that need to freeze a version for stabilisation or compliance testing. The key rule is that these branches are short-lived (a few days) and code always flows from trunk to the release branch, not the other way.
Adopt TBD incrementally
If your team has long-running feature branches, start by setting a maximum branch lifetime policy (e.g., "no branch lives longer than 3 days"). Gradually reduce it to 1 day. In parallel, invest in improving test speed and coverage. TBD is a destination you walk toward, not a switch you flip overnight.