backend / git / 10_branch_strategies.md

Branch Strategies

6 interview angles 5 min read source

Branch Strategies

How a team decides what branches exist, who creates them, and how they merge. The strategy shapes deploy cadence and release process more than tooling does.

The four common strategies

1. Trunk-based development

One long-lived branch (main/trunk). Short-lived feature branches (≤ 1 day) that merge to main. Continuous deployment from main.

main:    A───B───C───D───E───F   (deployed continuously)
              \           /
              feature  (merged in <1 day)
  • Pros: minimum branching cost, real CI/CD, no merge hell.
  • Cons: requires feature flags for half-built work, requires good test coverage.
  • Best for: SaaS web apps, modern teams with strong CI/CD.

This is what most modern, high-performing teams do. (See “DORA / Accelerate” research — trunk-based correlates with deploy frequency.)

2. GitHub Flow

Like trunk-based but with PR-style branches that may live a few days. Main is always deployable.

main:    A───B───C───────D───E
              \         /
              feature──(PR + review)
  • Pros: simple, PR-based review.
  • Cons: branches that live too long start to look like the next strategy.

GitHub themselves use this. Default for most open-source projects.

3. Git Flow (Vincent Driessen, 2010)

Multiple long-lived branches: main (production), develop (integration), feature/*, release/*, hotfix/*.

main:        A─────────────────M───────H
              \               /        |
              develop──D1──D2─/        |
                       \              |
                       feature        hotfix
  • Pros: clear release process; supports multi-version maintenance.
  • Cons: heavy ceremony, slow to deploy, encourages long-lived branches.
  • Best for: shipped software with explicit versions (desktop apps, mobile apps with App Store gates, embedded). Overkill for SaaS.

The author has since said it’s overused — most web teams should not adopt git-flow.

4. Release branches (the lightweight middle ground)

Trunk + occasional release branches for stabilization.

main:    ───A───B───C───D───E───F───G───
                     \
                  release/1.4 ── stabilize ── tag v1.4.0
                                          \── tag v1.4.1 (cherry-picked fixes)
  • Pros: simple core (trunk), supports versioned releases when needed.
  • Cons: cherry-picking fixes back/forward gets gnarly. Limit to 1-2 active release branches.

Picking one

Default for SaaS / web: Trunk-based or GitHub Flow. Short-lived branches, frequent merges, feature flags for incomplete work.

For shipped software with versioned releases: Trunk + release branches. Skip git-flow.

For “we have no convention”: GitHub Flow. It’s the easiest to onboard onto.

Branch naming conventions

Pattern Use
feature/<jira-id>-short-desc features tied to a ticket
fix/<short-desc> bug fixes
hotfix/<short-desc> urgent production fixes
chore/<short-desc> dependency bumps, refactors
experiment/<short-desc> spike, may never merge

Pick a convention and put it in the README. Tooling (Jira integrations, branch protection) often relies on the prefix.

Branch protection rules

For any branch that gets deployed (main, release/*):

  • No direct pushes — must go through a PR.
  • Required reviews — usually 1–2.
  • Required status checks — CI must pass.
  • Linear history — block merge commits if you want squash-only history.
  • Conversation resolution required before merge.
  • Signed commits for high-security repos.
  • No force pushes--force-with-lease would still bypass; explicitly disable for protected branches.

Configurable in GitHub Settings → Branches, GitLab Push Rules, Bitbucket Branch Permissions.

Long-lived feature branches — the trap

Anti-pattern: a branch that lives 3+ weeks. Symptoms:

  • Constant merge conflicts when you git pull main.
  • Reviewer can’t reasonably read all the changes.
  • Behavior diverges from main; surprise breakage on merge.

Avoidance:

  • Break the work into smaller PRs that ship behind a feature flag.
  • Rebase onto main daily.
  • If unavoidable: dedicate one engineer to keeping the branch in sync.

Feature flags as the alternative to long branches

Instead of “build the new checkout on a branch for a month,” merge incremental code to main behind:

if features.is_enabled("new_checkout", user):
    return new_checkout(user)
return old_checkout(user)
  • New code ships disabled (no user impact).
  • Toggle on for internal users → beta → percentage rollout → 100%.
  • Removes the branch-merge conflict problem entirely.

Flag tools: LaunchDarkly, Unleash, Statsig, Flipt, your own DB table.

Forks vs branches

Two ways to contribute to a repo you don’t have write access to:

Branch Fork
Where the branch lives original repo your own copy of the repo
Need write access? yes no — anyone can fork
Common in private/team repos open source
PR direction branch → main (same repo) fork → upstream

Open-source standard: fork → branch in fork → PR to upstream. Internal teams: branch directly in the shared repo, PR to main.

Tags vs branches

Both are pointers to commits, but:

Branch Tag
Moves with new commits? yes no — frozen pointer
Use active development mark a specific commit (release version)

Tag a release: git tag -a v1.4.0 -m "v1.4.0" then git push --tags. Annotated tags (-a) include author, date, message; lightweight tags are just refs.

Common interview confusions

  • “Trunk-based means no branches at all.” — short-lived branches (≤ 1 day) are fine. Just no long-lived integration branches.
  • “Git Flow is the standard.” — was popular ~2012; now considered overkill for most web teams. The author publicly walked it back.
  • “You can’t deploy from a branch.” — you can, but in trunk-based you usually deploy from main. Branch deploys are for staging/preview environments.

Interview angle

  • “What branch strategy does your team use and why?” — name the strategy, explain the deploy cadence and team size. Most modern web teams: GitHub Flow / trunk-based. Mention feature flags for in-progress work.
  • “What’s wrong with long-lived feature branches?” — merge hell, hard to review, behavior diverges from main, reviewer fatigue. Mitigate with smaller PRs + feature flags.
  • “When does Git Flow make sense?” — versioned shipped software (desktop, mobile, embedded) with multiple supported releases. Overkill for SaaS.
  • “What’s branch protection and what should you require on main?” — required reviews, required CI status checks, no direct pushes, no force pushes, linear history if you want squash-only.
  • “How do feature flags relate to branch strategy?” — they let you merge incomplete work to main safely, replacing long-lived branches with toggles. Enables true continuous deployment.
  • “Fork vs branch — when each?” — fork for open-source contributions where you don’t have write access; branch for internal team work where you do.