Skip to main content

Git Workflows — Trunk-Based vs GitFlow vs GitHub Flow

· 7 min read
Goel Academy
DevOps & Cloud Learning Hub

It is 4 PM on Friday. Your team has six feature branches, two of them have been open for three weeks, and someone just force-pushed to develop. The merge conflicts are so deep you are considering a career change. This is what happens when you pick the wrong Git workflow.

Why Your Branching Strategy Matters

Your Git branching strategy directly impacts how fast you ship, how often things break, and how much your developers want to quit. Pick the right one and merges are painless. Pick the wrong one and you spend more time resolving conflicts than writing code.

Let us break down the three major workflows and figure out which one fits your team.

GitFlow: The Enterprise Classic

Created by Vincent Driessen in 2010, GitFlow uses multiple long-lived branches to manage releases. It was designed for projects with scheduled releases.

The Branch Structure

# GitFlow branches
main # Production-ready code (tagged releases)
develop # Integration branch for features
feature/* # New features (branched from develop)
release/* # Release preparation (branched from develop)
hotfix/* # Emergency production fixes (branched from main)

GitFlow in Action

# Start a new feature
git checkout develop
git pull origin develop
git checkout -b feature/user-authentication

# Work on the feature...
git add .
git commit -m "feat: add JWT authentication middleware"
git commit -m "feat: add login and signup endpoints"
git commit -m "test: add auth integration tests"

# Finish the feature — merge back to develop
git checkout develop
git pull origin develop
git merge --no-ff feature/user-authentication
git push origin develop
git branch -d feature/user-authentication

# Create a release branch when ready
git checkout develop
git checkout -b release/2.1.0

# Fix bugs found during release testing
git commit -m "fix: correct session timeout value"

# Finish the release — merge to both main AND develop
git checkout main
git merge --no-ff release/2.1.0
git tag -a v2.1.0 -m "Release 2.1.0"
git push origin main --tags

git checkout develop
git merge --no-ff release/2.1.0
git push origin develop
git branch -d release/2.1.0

# Emergency hotfix from production
git checkout main
git checkout -b hotfix/fix-payment-bug
git commit -m "fix: resolve payment double-charge issue"

git checkout main
git merge --no-ff hotfix/fix-payment-bug
git tag -a v2.1.1 -m "Hotfix 2.1.1"

git checkout develop
git merge --no-ff hotfix/fix-payment-bug
git branch -d hotfix/fix-payment-bug

GitFlow works well when you have scheduled release cycles (every 2-4 weeks), need to maintain multiple versions in production, or have a QA team that tests release candidates. But for teams shipping continuously, it is often overkill.

GitHub Flow: Simple and Fast

GitHub Flow strips branching down to the bare minimum: main and short-lived feature branches. That is it. No develop, no release, no hotfix. Just main and branches.

GitHub Flow in Action

# Step 1: Create a branch from main
git checkout main
git pull origin main
git checkout -b add-search-functionality

# Step 2: Make commits
git add .
git commit -m "feat: add search index builder"
git commit -m "feat: add search API endpoint"
git commit -m "test: add search relevance tests"

# Step 3: Push and open a Pull Request
git push -u origin add-search-functionality
gh pr create --title "Add search functionality" \
--body "Implements full-text search using Elasticsearch"

# Step 4: Review, discuss, iterate
# (teammates review, CI runs, you push fixes)

# Step 5: Merge to main (deploys automatically)
gh pr merge --squash

# Step 6: Clean up
git checkout main
git pull origin main
git branch -d add-search-functionality

The key rules of GitHub Flow:

  1. main is always deployable
  2. Branch off main for any change
  3. Push to your branch frequently
  4. Open a PR when you want feedback (or are done)
  5. Merge to main after review
  6. Deploy immediately after merge

Trunk-Based Development: The Speed Demon

Trunk-Based Development (TBD) takes simplicity even further. Everyone commits to main (the "trunk") either directly or through very short-lived branches (less than a day old). Incomplete features are hidden behind feature flags.

Trunk-Based Development in Action

# Option A: Commit directly to trunk (small teams)
git checkout main
git pull origin main

# Make a small, incremental change
git add .
git commit -m "feat: add search button to navbar (behind flag)"
git push origin main

# Option B: Short-lived branch (larger teams)
git checkout main
git pull origin main
git checkout -b search-button # lives < 1 day

git add .
git commit -m "feat: add search button to navbar (behind flag)"
git push -u origin search-button

# Create PR — merged same day
gh pr create --title "Add search button (flagged)"
# After quick review:
gh pr merge --squash

# The feature flag in code
# Feature is deployed but hidden until flag is enabled

Feature flags are critical to TBD. You deploy incomplete code behind flags:

// Feature flag example
const featureFlags = {
SEARCH_ENABLED: process.env.FEATURE_SEARCH === 'true',
NEW_CHECKOUT: process.env.FEATURE_NEW_CHECKOUT === 'true',
};

function Navbar() {
return (
<nav>
<Logo />
<NavLinks />
{featureFlags.SEARCH_ENABLED && <SearchButton />}
</nav>
);
}

The Comparison Table

AspectGitFlowGitHub FlowTrunk-Based
ComplexityHigh (5 branch types)Low (2 branch types)Minimal (1 + short-lived)
Best Team Size10+ developers2-15 developersAny size (with discipline)
Release CadenceScheduled (weekly/monthly)ContinuousContinuous
Branch LifetimeDays to weeksHours to daysHours (max 1 day)
Merge ConflictsFrequent (long-lived branches)OccasionalRare (small changes)
Requires Feature FlagsNoNoYes
CI/CD Maturity NeededLowMediumHigh
Rollback StrategyHotfix branchRevert commitFeature flag toggle
Code ReviewOptionalRequired (PRs)Required (PRs or pair programming)
Best ForVersioned software, mobile appsWeb apps, SaaSHigh-performing teams, SaaS

Merge vs Rebase: The Eternal Debate

Regardless of your workflow, you need a strategy for integrating changes.

# Merge: Creates a merge commit, preserves history
git checkout main
git merge feature/login
# Result: A merge commit shows when the branch was integrated
# History: Non-linear but complete

# Rebase: Replays commits on top, linear history
git checkout feature/login
git rebase main
git checkout main
git merge feature/login # Fast-forward
# Result: Clean, linear history
# Tradeoff: Rewrites commit hashes

# Squash merge: Combines all branch commits into one
git checkout main
git merge --squash feature/login
git commit -m "feat: add login functionality"
# Result: One clean commit on main
# Tradeoff: Loses individual commit history from branch

# Interactive rebase: Clean up before merging
git checkout feature/login
git rebase -i HEAD~5
# Pick, squash, reword, or drop individual commits
# Clean up "WIP" and "fix typo" commits before merging

My recommendation: Use squash merges for feature branches into main. It keeps main clean and each commit represents a complete, reviewed feature.

Branch Protection Rules

No matter which workflow you choose, protect your critical branches:

# Using GitHub CLI to set branch protection
gh api repos/{owner}/{repo}/branches/main/protection \
--method PUT \
--field required_status_checks='{"strict":true,"contexts":["ci/tests","ci/lint"]}' \
--field enforce_admins=true \
--field required_pull_request_reviews='{"required_approving_review_count":1,"dismiss_stale_reviews":true}' \
--field restrictions=null \
--field required_linear_history=true

# What this enforces:
# - CI must pass before merge
# - At least 1 approval required
# - Stale reviews dismissed on new pushes
# - No direct pushes to main (even admins)
# - Linear history (squash or rebase only)

How to Choose Your Workflow

Use this decision tree:

Are you shipping a versioned product (mobile app, desktop software, library)?

  • Yes -> GitFlow (you need release branches and version tags)
  • No -> Continue

Does your team deploy to production multiple times per day?

  • Yes -> Trunk-Based Development (with feature flags and strong CI)
  • No -> Continue

Is your team comfortable with feature flags and have solid CI/CD?

  • Yes -> Trunk-Based Development
  • No -> GitHub Flow (simple, effective, minimal overhead)

Most web and SaaS teams should start with GitHub Flow and evolve toward Trunk-Based Development as their CI/CD pipeline and testing maturity improve.

The worst thing you can do is pick a workflow that is too complex for your team. A simple workflow executed well beats a sophisticated one executed poorly every time.


Next in our DevOps series, we will get hands-on with GitHub Actions and build your first CI/CD pipeline in 10 minutes.