Branching strategies (Git Flow, GitHub Flow, trunk-based)

A branching strategy is the team convention for which long-lived branches exist and how work flows into a release — the three canonical models trade isolation against integration speed.

Why it matters

The model dictates merge frequency, release cadence, and how painful conflicts get. Pick wrong and you get either chaos (no structure) or weeks-long divergent branches with brutal merges. The industry trend (DORA research) is decisively toward short-lived branches and frequent integration, because long-lived branches are the leading cause of merge hell and slow delivery.

How it works

StrategyLong-lived branchesBranch lifetimeBest forRelease
Git Flowmain, develop, release/, hotfix/Days–weeksVersioned products, scheduled releasesCut from release/*, tagged
GitHub Flowmain onlyHours–daysWeb apps, continuous deployDeploy main after PR merge
Trunk-basedmain (trunk)< 1 dayHigh-velocity CI/CD teamsContinuous; gate with flags
  • Git Flow (Driessen, 2010): features branch off develop, releases stabilize on release/*, urgent fixes go via hotfix/* straight off main. Powerful but heavy; often overkill today.
  • GitHub Flow: one rule — branch off main, open a PR, merge back, deploy. Simple, review-centric.
  • Trunk-based: everyone commits to main many times a day behind short branches or directly; incomplete work hides behind feature flags rather than long branches.

The deciding variable is branch age: the longer a branch lives, the more it diverges, so trunk-based minimizes it on purpose.

Example

GitHub Flow lifecycle:

main ──●──────────────●──  (deploy on each merge)
        \            /
         ●──●──●────/   feature/checkout  → PR #142 → squash-merge

Trunk-based with a flag — ship dark, enable later:

if flags.enabled("new_checkout"):   # merged to main today, off in prod
    return new_checkout()
return legacy_checkout()

Pitfalls

  • Cargo-culting Git Flow — its develop/release overhead hurts teams doing continuous deploy; the author later noted it’s wrong for web apps.
  • Long-lived feature branches — the universal anti-pattern; a 3-week branch guarantees conflict pain regardless of model.
  • Trunk-based without flags or CI — committing unfinished work to main with no flag gate or strong test suite breaks everyone.
  • Mixing modelsdevelop plus continuous deploy plus ad-hoc hotfixes confuses everyone; pick one and document it.

See also