Skip to content
Tools

Git Branching Strategies for Small Teams

Trunk-based development, GitHub Flow or Git Flow? A practical comparison for teams of two to ten developers, with the conventions that keep history clean.

Rahul Verma3 min read
Git branch graph with main, a feature branch and a fix branch merging back, plus a release tag
On this page

A branching strategy is a team agreement about how code moves from a laptop to production. The right one reduces merge conflicts, keeps main deployable and makes it obvious what is released. For small teams, simpler is almost always better.

The three strategies you will hear about

Trunk-based development

Everyone integrates into main (the trunk) at least daily, using very short-lived branches or direct commits behind feature flags. It needs good automated tests and a fast CI pipeline, and it rewards teams that deploy often.

GitHub Flow

A lightweight variant that most small teams adopt naturally:

  1. Branch from main for each change.
  2. Open a pull request early.
  3. Get a review and green CI.
  4. Merge to main and deploy.

main is always deployable. There are no long-lived develop or release branches.

Git Flow

Uses main, develop, feature, release and hotfix branches. It was designed for software with scheduled, versioned releases — such as installable apps or libraries supporting several versions. For continuously deployed web applications it usually adds ceremony without much benefit.

StrategyBest forMain cost
Trunk-basedFrequent deploys, strong CINeeds feature flags and discipline
GitHub FlowMost small web teamsPRs can linger if reviews are slow
Git FlowVersioned, scheduled releasesMany long-lived branches, more merges

Recommendation for most small teams: start with GitHub Flow and keep branches short-lived.

Conventions that make any strategy work

Name branches predictably

feature/search-autocomplete
fix/login-redirect-loop
chore/upgrade-node-20
docs/api-pagination

Keep branches short-lived

A branch open for two weeks accumulates conflicts and becomes risky to merge. Aim for pull requests that can be reviewed in under 30 minutes. Split large features behind a feature flag if necessary.

Write useful commit messages

feat(search): add debounced autocomplete to header search

Queries fire 250ms after the last keystroke and cancel the
previous request, reducing API calls while typing.

A short imperative summary plus a body explaining why helps whoever reads the history later — often you.

Update your branch safely

git fetch origin
git switch feature/search-autocomplete
git rebase origin/main        # replay your commits on the latest main
# resolve conflicts, then:
git push --force-with-lease

Use --force-with-lease, not --force, so you never overwrite a teammate’s pushed work by accident. Never rebase a shared branch that others are committing to.

Automate the boring checks

Branching rules work best when CI enforces them. A minimal GitHub Actions workflow that runs on every pull request:

name: ci
on:
  pull_request:
  push:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run lint
      - run: npm test

Combine this with branch protection so a pull request cannot be merged until the checks pass. Reviewers can then focus on design and readability instead of spotting failing tests.

Protect main

On GitHub, enable branch protection (or rulesets) for main:

  • Require a pull request before merging.
  • Require status checks (tests, lint) to pass.
  • Require at least one approval.
  • Block force pushes and deletions.

Squash, merge or rebase?

  • Squash merge turns each PR into one commit on main. Clean history, one commit per change — a good default for small teams.
  • Merge commits preserve every commit and show where branches joined. Useful when individual commits are carefully curated.
  • Rebase merge keeps individual commits but no merge commit.

Pick one and configure the repository to allow only that option, so history stays consistent.

Releases and hotfixes

Tag releases on main (v1.4.0) so you can always see exactly what was deployed. For an urgent fix, branch from main, fix, review and merge like any other change — with GitHub Flow there is no separate hotfix process to remember.

The best strategy is the one your whole team follows consistently. Write it down in your CONTRIBUTING.md, keep it short, and revisit it when the team or release process changes.

Written by

Rahul Verma

DevOps & cloud · containers and CI/CD

Writes hands-on guides to containers, cloud services and the automation that ships software safely. (Demo author profile.)

Comments

Join the discussion

Your email address will not be published. Be kind and stay on topic.