What is trunk-based development, and how does it change branching strategy compared to long-lived feature branches or GitFlow?
Quick Answer
Trunk-based development is a workflow where every engineer merges small, frequent changes directly into a single shared branch (the trunk, usually main) at least once a day, instead of working in isolation on long-lived feature branches. It exists to support continuous integration, since CI can only catch conflicts and regressions early if code is actually integrated early.
Detailed Answer
Think of trunk-based development like a group of editors working on a single shared newspaper article, each making small edits and reading each other's changes constantly throughout the day, versus GitFlow's approach of sending each editor off to write an entirely separate section in isolation for two weeks and then trying to stitch all the sections together into one coherent article at the end. The second approach guarantees a painful, high-conflict merge day; the first catches disagreements while they're still small and easy to resolve.
GitFlow, popularized around 2010, defines long-lived branches for develop, feature, release, and hotfix work, with features often living in isolation for weeks before merging. It made sense for software shipped in infrequent, versioned releases (like desktop installers), where a long stabilization period before each release was normal. Trunk-based development was designed for the opposite reality: teams deploying multiple times a day, where a two-week-old feature branch has already drifted so far from main that merging it is its own multi-day project, and where you can't wait weeks to discover that two features conflict.
Mechanically, trunk-based development means branches, if used at all, live for hours, not weeks — a developer branches, commits a small piece of work, opens a pull request, and merges back to main the same day, often multiple times a day. Work that isn't ready for users yet is hidden behind feature flags rather than kept out of main on a separate branch, so main is always deployable even while a feature is only half-built. CI runs against every merge to main, and because merges are small and frequent, when CI fails, it's obvious which tiny change caused it — compare that to GitFlow, where a failing merge could be caused by any of hundreds of commits accumulated over two weeks.
In production, this is what actually makes continuous deployment possible: CD pipelines assume main is always in a releasable state, which is only true if nothing large and unreviewed has been sitting unmerged. Teams practicing trunk-based development typically see far fewer, smaller merge conflicts and can pinpoint regressions to a single day's commits during an incident.
The gotcha: trunk-based development requires feature flags and strong automated test coverage to work safely — without them, teams end up merging half-finished, untested code straight to main just to satisfy the 'merge daily' rule, which trades merge-conflict pain for production-stability pain instead of actually solving the underlying problem.