Gitflow was designed in 2010 for teams doing scheduled releases with long-lived support branches. Most teams today deploy continuously. Running Gitflow on a continuous deployment team means paying for a coordination overhead that no longer matches how the software leaves the building.
This is the workflow that replaces it: trunk-based development with feature flags. Fewer branches, fewer merge conflicts, faster time from commit to production.
Prerequisites
A CI pipeline that runs tests on every push
Ability to deploy from
maindirectly (or close to it)A feature flag tool — LaunchDarkly, Unleash (open source, self-hostable), or a simple in-house flag table
The core structure
One long-lived branch: main. Everything deploys from it.
main ──●──●──●──●──●──●──●──●──▶
\ / \ /
feature/x feature/y
Short-lived feature branches fork from main and merge back within a day or two. No develop branch. No release branch. No long-lived hotfix branch.
Step 1: Branch for a feature
git checkout main
git pull origin main
git checkout -b feature/checkout-retry-logic
Naming convention: feature/, fix/, or chore/ prefix, then a short description. This keeps branch lists scannable and makes intent visible without opening the diff.
Step 2: Keep the branch short-lived
Target: merged within 1–2 days. If a feature is going to take longer, that's a signal to split it, not a reason to extend the branch.
Commit and push regularly:
git add .
git commit -m "Add retry logic for failed checkout requests"
git push origin feature/checkout-retry-logic
Rebase against main daily to stay current:
git fetch origin
git rebase origin/main
Long-lived branches are where merge conflicts compound. A branch that's a day old conflicts with almost nothing. A branch that's three weeks old conflicts with everything that shipped in those three weeks.
Step 3: Gate incomplete work behind a feature flag
This is the part that makes trunk-based development possible. Code that isn't ready for users still merges to main — it's just gated.
if (featureFlags.isEnabled('checkout-retry-logic', user)) {
return retryCheckout(order);
} else {
return standardCheckout(order);
}
The flag decouples deploy from release. The code ships to production dark. Turning it on for users is a separate, instant, reversible action — no deploy required.
Step 4: Open the PR against main
git push origin feature/checkout-retry-logic
Open the PR through your git host. Required for merge:
CI passing (tests, linting, type checks)
One reviewer approval
No unresolved comments
Keep the PR small enough to review in one sitting. A 40-line PR gets a careful review. A 900-line PR gets a skim and an approve.
Step 5: Merge and delete the branch
Squash merge to keep main's history readable — one commit per feature, not fifteen "wip" commits:
git checkout main
git pull origin main
git merge --squash feature/checkout-retry-logic
git commit -m "Add retry logic for failed checkout requests"
git push origin main
git branch -d feature/checkout-retry-logic
git push origin --delete feature/checkout-retry-logic
Most git hosts (GitHub, GitLab) do this through the PR UI with a "Squash and merge" button — same result, no terminal required.
Step 6: Roll out through the flag, not through git
Deploy ships the code dark. Rollout happens through the flag dashboard:
Enable for internal team first
Enable for 5% of users, watch error rates and metrics
Ramp to 25%, 50%, 100% over hours or days
Remove the flag and the old code path once fully rolled out
If something breaks at any stage, flip the flag off. No revert, no redeploy, no incident response measured in minutes-to-rollback. It's instant.
Handling production fixes
No hotfix branch. A production bug gets the same treatment as any other change:
git checkout main
git pull origin main
git checkout -b fix/checkout-crash-on-empty-cart
Same PR process, same CI gate, same squash merge. Small scope means it moves fast without needing a separate escape hatch. The hotfix branch pattern exists to bypass process — the fix here is having a process that doesn't need bypassing.
What this costs you
Trunk-based development assumes strong CI and a real testing culture. Skip that, and code merges to main broken more often. The feature flag system also becomes a second thing to maintain and eventually clean up — a flag left in the codebase six months after full rollout is dead weight.
Neither cost outweighs what Gitflow charges in return: merge conflict resolution as a recurring tax, release branches that drift from main for weeks, and a mental model where "done" and "deployed" and "released" are three different states instead of one.