There isn’t one “best” branching model for every team. GitFlow and Trunk-Based Development are two popular approaches that optimize for different goals: predictable releases vs. rapid delivery. I’ve used GitFlow for many years. My current team on the other hand, uses Trunk-Based development and it fits well for our current workflow. We are concentrating on very small work units and we’re constantly merging those into our main branch, several times a week. Those traverse a few non-prod environments and makes into production, pretty much on a weekly cadence. I’ll provide some explanation of each strategy, below.
GitFlow (release-oriented)
GitFlow uses a few long-lived branches:
main(ormaster) holds production-ready code.developis where completed features accumulate before a release.- Short-lived branches exist for
feature/*,release/*, andhotfix/*.
Simple example: building a login feature
- Create the long-lived branches (if they don’t exist yet):
# create develop from main git checkout -b develop origin/main git push origin develop
- Build a feature on top of
develop:
git checkout develop git checkout -b feature/login # ...code, tests, commits... git push origin feature/login
- Merge the feature back into
develop(via PR):
git checkout develop git merge feature/login
- When it’s release time, cut a
releasebranch:
git checkout -b release/1.2.0 develop # finish polish/bugfixes here
- Ship the release by merging into
main, tagging, then back-merging todevelop:
git checkout main git merge release/1.2.0 git tag v1.2.0 git push origin main --tags git checkout develop git merge release/1.2.0
Why teams like GitFlow: it supports multiple active release versions, gates change at release boundaries, and fits organizations with slower deployment cycles.
Trunk-Based Development (continuous delivery)
Trunk-based development minimizes long-lived branches. The trunk is main, and changes are merged frequently (often daily) behind feature flags.
Typical rules:
- Branches are small and short-lived (hours/days).
- Each branch must keep
mainreleasable (tests, CI gates, feature flags). - Merge early, merge often.
Simple example: adding a small UI tweak
- Branch from
main:
git checkout main git pull git checkout -b feat/quick-ui-tweak # ...small change, tests... git push origin feat/quick-ui-tweak
- Merge quickly once CI passes and review is done:
git checkout main git pull git merge --no-ff feat/quick-ui-tweak git push origin main git branch -d feat/quick-ui-tweak
Why teams like Trunk-Based Development: it reduces merge hell, keeps feedback loops short, and supports continuous delivery.
Which should you use?
- Choose GitFlow if you have strict release gates, multiple supported versions, or long-lived release branches.
- Choose Trunk-Based Development if your main priority is fast iteration, frequent deploys, and minimizing long-running branches.
The most important part is consistency: pick a model that matches your release cadence and automation maturity, then enforce it with clear rules, CI checks, and code review.
