Git Workflows Compared — Gitflow, Trunk-Based, and GitHub Flow 2026

Sanjeev SharmaSanjeev Sharma
7 min read

Advertisement

Introduction

Why This Matters

The branching strategy your team uses shapes everything downstream: how long code sits unreviewed, how merge conflicts accumulate, how quickly bugs can be hotfixed, and how reliably you can deploy. Teams that mismatch their workflow to their release cadence end up with either chaotic main branches or months-long integration nightmares.

Choosing the right workflow is a force multiplier — the right choice makes CI/CD faster, deployments safer, and collaboration smoother.

Gitflow — Structured Releases with Long-Lived Branches

Gitflow uses two permanent branches (main and develop) plus three types of temporary branches (feature/, release/, hotfix/). It was designed for software with scheduled, versioned releases.

Branch structure:

main        ──────────────────────────────────────► (production releases, tagged)
              ↑  merge release/1.0          ↑  merge hotfix/1.0.1
develop     ──────────────────────────────────────► (integration branch)
              ↑  merge feature/auth  ↑  merge feature/dashboard

Feature development:

# Start from develop, not main
git checkout -b feature/user-auth develop
 
# Regular commits on the feature branch
git commit -m "feat: add JWT authentication"
git commit -m "feat: add refresh token logic"
git push origin feature/user-auth
 
# Open a pull request to develop, then after review:
git checkout develop
git merge --no-ff feature/user-auth
git push origin develop
git branch -d feature/user-auth

Releasing:

# Cut a release branch from develop
git checkout -b release/1.2.0 develop
 
# Only bugfixes and version bumps on this branch
npm version 1.2.0
git commit -am "chore: bump version to 1.2.0"
 
# Merge into main (production) and tag it
git checkout main
git merge --no-ff release/1.2.0
git tag -a v1.2.0 -m "Release version 1.2.0"
git push origin main --tags
 
# Back-merge into develop to keep it in sync
git checkout develop
git merge --no-ff release/1.2.0
git push origin develop
git branch -d release/1.2.0

Hotfixing production:

git checkout -b hotfix/payment-bug main
git commit -m "fix: correct payment calculation rounding error"
 
# Merge to main (deploy immediately)
git checkout main
git merge --no-ff hotfix/payment-bug
git tag -a v1.2.1 -m "Hotfix 1.2.1"
git push origin main --tags
 
# Bring the fix into develop too
git checkout develop
git merge --no-ff hotfix/payment-bug
git push origin develop
git branch -d hotfix/payment-bug

When to use Gitflow: Teams shipping mobile apps, desktop software, SaaS with multiple supported versions, or products with compliance-mandated release windows. Not recommended for teams deploying multiple times per day.

Trunk-Based Development — Speed and Continuous Deployment

In Trunk-Based Development (TBD), all developers commit directly to main (the "trunk") or use very short-lived branches (1–2 days maximum) before merging. CI runs on every commit and deployment is continuous.

# Create a short-lived branch (max 1-2 days)
git checkout -b feat/add-search-filter
 
# Small, focused commits
git commit -m "feat: add search filter component"
git push origin feat/add-search-filter
 
# Open PR immediately, merge the same day
# After merge, delete branch
git checkout main
git pull
git branch -d feat/add-search-filter

Feature flags for incomplete work:

// Use flags to ship incomplete features safely
const isNewCheckoutEnabled = featureFlags.get('new-checkout-v2')
 
if (isNewCheckoutEnabled) {
  return <NewCheckout />
}
return <LegacyCheckout />

Feature flags let you merge unfinished code to main without exposing it to users. This keeps branches short-lived while decoupling deploy from release.

When to use TBD: Teams deploying multiple times per day, teams using continuous deployment pipelines, companies practicing DevOps at scale (Google, Meta, and Shopify use variants of this). Requires mature CI/CD and a culture of small commits.

GitHub Flow — Simple and Practical

GitHub Flow is a simplified model with one rule: main is always deployable. Every change goes through a pull request from a feature branch:

# 1. Create a branch from main
git checkout -b feature/dark-mode main
 
# 2. Develop with regular commits
git commit -m "feat: add dark mode toggle to settings"
git commit -m "feat: persist dark mode preference to localStorage"
git push origin feature/dark-mode
 
# 3. Open a PR — discuss, review, refine
 
# 4. Deploy to staging from the branch (optional)
# 5. Merge to main → auto-deploy to production
 
# 6. Delete the branch
git push origin --delete feature/dark-mode
git branch -d feature/dark-mode

GitHub Flow removes the complexity of Gitflow (no develop branch, no release branches) while still enforcing code review via pull requests. It works best when you deploy frequently but do not need the rigidity of Gitflow.

When to use GitHub Flow: Web applications with frequent deployments, small-to-medium teams, open source projects on GitHub. Simpler than Gitflow, less rigorous than TBD.

Comparing the Three Workflows

DimensionGitflowTrunk-BasedGitHub Flow
Main always deployableOnly after releaseYesYes
Branch lifetimeWeeks–monthsHours–2 daysDays–1 week
Deployment frequencyScheduledContinuousFrequent
Rollback mechanismPrevious tagFeature flag offRevert PR
ComplexityHighLow (needs discipline)Low
Best forVersioned softwareHigh-velocity teamsWeb SaaS

Common Mistakes

  • Using Gitflow for a web SaaS — If you deploy weekly or more, Gitflow adds overhead with no benefit. Switch to GitHub Flow or TBD.
  • Long-lived feature branches in TBD — Branches lasting more than 2 days defeat the purpose of TBD and reintroduce merge conflict accumulation.
  • Merging develop into main without a release branch — This bypasses the QA stabilization phase that Gitflow's release branches provide.
  • No branch protection rules — All three workflows depend on main being stable. Always require PR reviews and CI passing before merging to main.
  • Forgetting to back-merge hotfixes — In Gitflow, a hotfix merged to main without merging back to develop causes the fix to regress in the next release.

Best Practices

  • Enforce branch protection: require at least one reviewer and green CI before any merge to main.
  • Regardless of workflow, keep pull requests small — PRs under 400 lines get reviewed 2–3x faster than larger ones.
  • Use conventional commits (feat:, fix:, chore:) to auto-generate changelogs and drive semantic versioning.
  • Tag every production release with a semantic version so you can identify and roll back to any deployed state.
  • In TBD and GitHub Flow, configure auto-deploy from main so deployment is a consequence of merging, not a separate manual step.

Key Takeaways

  • Gitflow uses main, develop, feature/, release/, and hotfix/ branches — ideal for versioned, scheduled releases.
  • Trunk-Based Development keeps all branches alive for at most 1–2 days, relying on feature flags to ship incomplete work safely.
  • GitHub Flow has one rule: main is always deployable, and all changes go through a pull request.
  • The correct workflow depends on release cadence: scheduled releases favor Gitflow, continuous deployment favors TBD or GitHub Flow.
  • Feature flags are a key enabler of TBD — they decouple code deployment from feature release.
  • In Gitflow, hotfixes must be merged back to both main and develop to prevent regressions in the next release.
  • All three workflows benefit from branch protection rules that require CI to pass and at least one reviewer to approve.
  • Small, focused pull requests (under 400 lines) are reviewed faster and merge with fewer conflicts in any workflow.

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro

Related reading