A branching strategy is your team’s agreement on how work flows through Git: where features are developed, how they’re reviewed, and what gets deployed. The right choice depends on how often you deploy, and how many versions you maintain. For most web apps on a VPS, simpler is better.

The main models

Model Branches Best for
Trunk-based development main + very short-lived branches (hours to a day) Teams with strong CI, continuous deployment
GitHub Flow main + feature branches merged via pull requests Most web apps and SaaS
GitFlow main, develop, feature/*, release/*, hotfix/* Versioned software with scheduled releases
Release branches main + release/1.x, release/2.x Maintaining several supported versions

GitHub Flow (a good default)

  1. Branch from main: git switch -c feature/invoice-export.
  2. Commit, push, open a pull request.
  3. CI runs tests. A teammate reviews.
  4. Merge to main (squash or merge commit).
  5. main deploys to production (automatically, or with a manual approval).
git switch main && git pull
git switch -c fix/login-redirect
# … work …
git push -u origin fix/login-redirect

Rule: main is always deployable. Release versions with tags. See Git tags and releases.

Trunk-based development

Everyone integrates into main at least daily. Unfinished features hide behind feature flags rather than living in long-running branches. It minimises merge conflicts, and suits teams that deploy many times a day. See feature flags.

GitFlow

  • develop collects finished features. main only receives releases.
  • release/x.y branches stabilise a version. hotfix/* patches production.

It adds ceremony and merge overhead. It’s useful for software shipped to customers in versions (desktop apps, libraries, on-premises products), and usually unnecessary for a website or SaaS deployed continuously.

Environments: branches or tags?

Avoid branch-per-environment setups (dev, staging, prod branches that drift apart). Prefer:

  • one main branch;
  • deploy the same commit or image tag to staging, then production;
  • promote by tag or approval, not by merging between environment branches.

See deployment strategies and Docker image tags best practices.

Branch protection

On GitHub, GitLab or Gitea, protect main:

  • require pull requests and at least one review;
  • require CI status checks to pass;
  • disallow force pushes and deletions;
  • optionally require linear history (squash or rebase merges).

See Gitea and CI/CD pipeline explained.

Naming conventions

feature/short-description
fix/issue-123-login-loop
chore/update-dependencies
release/1.9
hotfix/1.8.4

Short, lowercase, with a type prefix: easy to filter, and easy to automate (for example labels and changelogs).

Merge style

  • Squash merge: one clean commit per pull request on main. Easy to revert.
  • Merge commit: keeps branch history.
  • Rebase: linear history, without merge commits.

See git merge vs rebase.

Quick reference

Situation Strategy
Web app / SaaS, small team GitHub Flow
Many deploys per day, strong CI Trunk-based + feature flags
Versioned product, scheduled releases GitFlow or release branches
Environments Same artifact promoted by tags/approvals
Always Protected main, CI required

Related: Git commands cheat sheet and Git hooks.

  • Git
  • DevOps
  • Collaboration