HomeProjectsBlogContact

Git Branching Strategies: Trunk-Based, GitHub Flow and Git Flow

How your team uses branches shapes how fast you ship and how painful merges are. The three common strategies compared, plus commit message conventions and the rebase vs merge question.

Git Branching Strategies: Trunk-Based, GitHub Flow and Git Flow

Every team using Git ends up with a branching strategy, whether they chose one or not. A good one keeps merges small and releases calm. A bad one produces week-long branches, nightmare merge conflicts and "which branch is production again?" moments.

Here are the three strategies you'll meet most, and how to pick.

Trunk-based development

Everyone integrates into one main branch (the "trunk") frequently, at least daily. Feature branches, if used at all, live for hours or a day or two.

  • How unfinished work stays hidden: feature flags. Code ships to production switched off and gets turned on when ready.
  • What makes it work: strong automated tests and CI on every commit.
  • Pros: tiny merges, almost no conflicts, continuous delivery, problems surface early.
  • Cons: requires discipline, good test coverage and some feature-flag tooling.

GitHub Flow

A simple, popular middle ground:

  1. main is always deployable.
  2. Create a short-lived branch for each feature or fix.
  3. Open a pull request, get a review, pass CI.
  4. Merge to main and deploy.
git switch -c fix/checkout-rounding
# ...commit work...
git push -u origin fix/checkout-rounding
# open PR -> review -> merge -> deploy
  • Pros: easy to learn, works perfectly with pull request reviews and preview deployments.
  • Cons: if branches live too long, it slides into painful merges.

For most web teams and solo developers, GitHub Flow with short-lived branches is the sweet spot.

Git Flow

A more structured model with several long-lived branches: main for releases, develop for integration, plus feature/*, release/* and hotfix/* branches.

  • Pros: clear process for versioned software with scheduled releases and multiple supported versions (mobile apps, desktop software, libraries).
  • Cons: heavy for continuously deployed web apps. More branches, more merges, more places for code to go stale.

If you deploy a web app many times a week, Git Flow usually adds ceremony without benefit.

Choosing

Situation Good fit
Solo developer or small team, web app GitHub Flow
Experienced team, strong CI, many deploys per day Trunk-based
Versioned releases, mobile/desktop apps, supporting old versions Git Flow (or a lighter release-branch variant)

The single most important rule, whatever you choose: keep branches short-lived. The longer a branch lives, the more it diverges, and the harder the merge.

Branch naming

Consistent names make branch lists readable:

feature/invoice-export
fix/login-redirect-loop
chore/upgrade-dependencies
docs/api-pagination

Include a ticket number if your team uses a tracker: fix/1423-login-redirect-loop.

Commit messages that help future you

A good commit message explains why, because the diff already shows what.

Fix rounding error in checkout total

Totals were rounded per line item and then summed, which could differ
from the payment provider's total by a cent. Round once, at the end.

Many teams use Conventional Commits, a lightweight format that tools can read to generate changelogs and version numbers:

feat: add CSV export for invoices
fix: prevent double submission on checkout
docs: document pagination parameters
chore: upgrade test dependencies

Keep commits focused on one logical change. It makes reviews, reverts and git bisect much easier. (Debugging with git bisect.)

Rebase or merge?

Both combine work from two branches; they just record history differently.

  • Merge keeps history exactly as it happened, with merge commits.
  • Rebase replays your commits on top of the latest main, producing a straight, linear history.

A common, sensible approach:

  • Rebase your own feature branch on main to stay up to date (git pull --rebase), before it's shared widely.
  • Never rebase branches others are working on, since it rewrites history they depend on.
  • Squash-merge PRs if you want one clean commit per feature on main.

If a rebase goes wrong, git rebase --abort and git reflog will get you back. (Undoing Git mistakes.)

Protect the main branch

Whatever the strategy, protect main:

  • Require pull requests and at least one review
  • Require CI to pass
  • Block force pushes

These settings make it hard for broken code to land by accident. (Code review practices.)

FAQ

What is the best Git branching strategy?

For most web teams, GitHub Flow: a deployable main and short-lived feature branches merged through pull requests. Mature teams with strong CI often move toward trunk-based development.

What is the difference between Git Flow and GitHub Flow?

Git Flow uses several long-lived branches (main, develop, release and hotfix branches) for scheduled releases. GitHub Flow uses only main plus short-lived feature branches, suiting continuous deployment.

Should I use rebase or merge?

Rebase your own unshared branches to keep them current and tidy; merge (or squash-merge) when integrating into shared branches. Never rebase a branch others are using.

Keep reading

More from the workbench

All articles →