How do I position feature flags when moving from Gitflow to Trunk-Based?
Question
We're a 20-person team. In Gitflow we work across `feature`/`develop`/`release`/`master` branches, but merges drag on (conflicts) and release cycles take weeks. To move to a Continuous Delivery culture, we plan to switch to Trunk-Based. In this model where code goes straight to the main branch in small chunks, how do I position the feature flag architecture to keep unfinished features from going live?
Answer
Short answer: in Gitflow, painful merges and week-long releases come precisely from long-lived branches drifting. Trunk-Based fixes that by merging small changes to main continuously; but feature flags are what enforce “an unfinished feature on main can’t reach users.”
Short answer
The issue: you want to merge code often, but you don’t want half-done work leaking to production. Flags bridge that contradiction. I gathered what branch, merge, and PR discipline looks like in production in the Git guide; this transition is built on top of that discipline.
Why
-
Long-lived branches are the problem itself.
feature/develop/releasebranches drift from main over time; conflicts and week-spanning releases are born right there. -
Flags decouple deploy from release. You deploy code whenever you want (deploy), and turn the feature on when it’s ready (release). This split also gives you per-flag canary/gradual rollout — you can open the same version to 5% of users and watch.
-
Flags you never clean up create a new debt. Dead flags turn into their own technical debt and muddy the codebase; treating a flag as a permanent structure just swaps the old problem for a new one.
What to do
-
Remove the long-lived branches and merge to main continuously. In Trunk-Based you merge changes to main continuously, in small chunks; as branch lifetime shrinks, conflicts and release cycles shrink with it.
-
Keep unfinished work “dark” behind a flag. Put the incomplete feature behind a flag that’s off in prod, and still merge the code to main daily. When the feature is done and tested, you flip the flag. The code is live but invisible to users.
-
Discipline is mandatory: short-lived branches, strong CI, flag hygiene. Branches should live a day or two, and CI must run solid on every merge. Most critical is flag hygiene: clean up dead flags.
Bottom line: for a 20-person team aiming at Continuous Delivery, the right model is Trunk-Based + feature flags. I’d keep branches short, merge everything behind flags, and treat flags as temporary — removing them the moment a feature is done. When exactly, and under what preconditions, I move to Trunk-Based, I detail on sade.dev.
Related Reading
Comments
Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.