← back to the section

Git doesn't impose a process: branches are cheap, do whatever you want. That's why every team picks a branching model — an agreement on which branches live in the project, where to branch from, and where to merge into. Many models have been invented over fifteen years, but in practice the choice comes down to three. You need to know them both to plug into a new team's process quickly and to understand why processes differ so much.

One number tells them apart: how long work lives away from the shared branch — weeks, days, or hours. Everything else follows from that.

Git Flow: two long-lived branches, three temporary v1.0 main hotfix release develop feature v1.1 v1.2 GitHub Flow: one main, branches live for days main branch → pull request branch → pull request deploy deploy trunk-based: the trunk, hours-long branches, flags main one-day branch behind a feature flag branch life hours days weeks

Three models in turn on one canvas. Git Flow: main with version tags and develop live forever, while feature, release and hotfix come and go; work stays aside for weeks, and a hotfix has to return into both main and develop — otherwise the fix is lost. GitHub Flow: one main, a short branch through a pull request, a deploy after every merge. Trunk-based: tiny commits straight into the trunk, a rare one-day branch, anything unfinished hidden behind a feature flag. The marker at the bottom shows how branch life shrinks from model to model.

Git Flow: the heavyweight of the release era

The 2010 classic: two long-lived branches — main (releases only, each marked with a tag) and develop (integration of current development) — plus three kinds of temporary ones: feature/* (from develop, into develop), release/* (release preparation: stabilization, versions), hotfix/* (an urgent fix from main, merged into both main and develop).

Its strength is parallel versions: while develop accumulates v2.4, a release branch stabilizes v2.3, and a hotfix patches v2.2 in production. Its weakness is ceremony: many branches, many merges, and a forgotten "hotfix into develop" is a classic source of regressions.

Where it fits: boxed products, mobile apps with release trains, enterprise with parallel version support. For continuously deployed web services, Git Flow today is excessive (even its author has admitted as much).

GitHub Flow: simple and built around PRs

One long-lived branch — main, always ready to deploy. Everything else is short branches off main, merged back through a pull request with review and a green pipeline. Merged — deployed.

Strengths: minimal ceremony, speed, a natural pairing with code review and CI. Weakness — no standard place for "release stabilization" and parallel versions: there is always just one main.

Where it fits: web services and teams with continuous delivery — that is, most modern product teams. If you're unsure where to start, start with this.

Trunk-based: speed at the limit

A radical evolution of the same idea: everyone commits to main (the "trunk") in very small portions — either directly or through one-day branches. Integration happens continuously, conflicts nearly vanish (there's nothing left to diverge), and delivery speed is maximal.

The price is engineering-culture maturity. Unfinished features land in main and hide behind feature flags (the code is in production but switched off by config); without strong automated testing and discipline, trunk-based turns into chaos. In return, this is exactly the model that correlates with elite DORA metrics — software delivery research consistently links short-lived branches with high speed and stability.

Where it fits: teams with mature CI, fast review, and automated tests; large engineering organizations (Google lives on a monorepo with a trunk).

How to choose

The questions that decide the choice:

  • How many versions do you support at once? Several — Git Flow (or its release part). One, with production always fresh — GitHub Flow / trunk-based.
  • How often do you deploy? Release trains once a month can tolerate ceremony; deploying many times a day demands a lightweight model.
  • How mature are your automated tests and review? Trunk-based without them is dangerous; GitHub Flow is the workable middle ground.

And most importantly: a model is a team agreement, not a dogma. Real processes are often hybrids ("GitHub Flow plus a release branch before a major version") — what matters is that the agreement is explicit and understood the same way by everyone. How branching connects to the delivery pipeline and versioning — in the article on branches and the release cycle.

In short

  • Git Flow: main+develop+feature/release/hotfix — for parallel versions and release trains; excessive for continuous deployment.
  • GitHub Flow: one main + short branches through PRs — the default for modern product teams.
  • Trunk-based: mini-portions into the trunk + feature flags — maximum speed given mature tests and culture.
  • The longer a branch lives away from main, the more expensive the merge: that is where the difference between models comes from.
  • The choice is driven by: number of supported versions, deployment frequency, automation maturity.
  • A model is an explicit team agreement; hybrids are normal.