Last modified: September 13, 2025

This article is written in: 🇺🇸

Strategies for Branching

Before choosing a branching strategy, it helps to decide what you’re optimizing for: speed, safety, or simplicity. Different teams and projects lean different ways—startups with small codebases won’t work the same as larger, multi-repo setups. This overview lays out the options and how to adapt them to your workflow.

Trunk-Based Development

In trunk-based development, a single long-lived branch—usually main, master, or trunk—is the integration point for all code. Small, short-lived feature (topic) branches are fine, but they must merge back to trunk quickly—ideally within hours, and rarely later than a day or two.

Every commit to trunk triggers the CI pipeline: it builds, runs the full automated test suite, performs static analysis, and—if green—deploys to a staging/integration environment. After acceptance tests pass, the same artifact is promoted toward production unchanged.

This approach depends on continuous integration, strong automated tests, and fast feedback loops so trunk stays releasable.

Main Branch (Trunk)
   |
   |——> Continuous Integration (CI)
   |         |
   |         v
   |  Automated Testing
   |
   |——> Short-Lived Feature Branches (optional)
   |         |
   |         v
   |  Feature Development
   |
   |——> Merge Back to Trunk (at least daily)
   |
   |——> Staging → Production Release

How are big breaking changes introduced?

Use incremental, backward-compatible steps: feature flags/toggles, branch by abstraction, and “expand/contract” migrations (e.g., add new paths first, dual-write, then remove the old). If a short branch is unavoidable, keep it tiny, merge daily, and hide behavior behind flags.

Is every commit here a transaction? Treat each commit as atomic and releasable: it should build, pass tests, and leave user-visible behavior unchanged by default (flags off). Commits trigger CI and often deploy to staging, but releases to users are controlled by flag flips or artifact promotion—not by every commit.

Advantages

Disadvantages

When to Use

Critique

Release Branches

In the release-branching workflow, each upcoming version is stabilised on its own branch while everyday feature work continues elsewhere. A typical setup includes:

main
 │
 ├──▶ develop
 │       │
 │       ├──▶ Feature branches (feat/XYZ)
 │       │        │
 │       │        ▼
 │       │  Merge back to develop
 │       │
 │       └──▶ Release-X.Y branch
 │                │
 │                ├──▶ Bug fixes / final hardening
 │                │
 │                └──▶ (if urgent) Hotfix branch
 │                         │
 │                         ▼
 │                     Merge to Release-X.Y
 │
 ├──▶ Merge Release-X.Y → main & tag vX.Y.0
 │
 ▼
Production deployment

Once the release branch is declared stable:

  1. Merge into main and create an annotated, immutable tag (vX.Y.0) for traceability.
  2. Merge (or rebase) back into develop so ongoing work includes all post-freeze fixes.
  3. Delete (or archive) the release branch to avoid clutter.

Advantages

Disadvantages

When to Use

Not the same as Git Flow

Git Flow is a full branching methodology. Release branches are a single ingredient—often used within Git Flow, but also viable on their own.

Critique

Feature Branches

In a feature-branch workflow, each new capability, enhancement, or bug fix lives on its own branch cut from a stable integration branch (main or, more often, develop). Work proceeds in isolation until the change set is complete and the CI pipeline is green. The branch is then merged back via a pull/merge request after code review and automated checks. The resulting commits flow to production in the next release train—or immediately, if you practise continuous delivery.

Typical naming conventions: feat/<ticket-id>-<slug> for new functionality and fix/<ticket-id> for defects. This keeps context clear for both tooling and humans.

main
 │
 ├──▶ develop   (optional integration branch)
 │       │
 │       ├──▶ feat/ABC-123-cool-feature
 │       │        │
 │       │        ▼
 │       │   Commit → test → review
 │       │        │
 │       └──▶─────┘  Merge to develop
 │
 └──▶ (CI) → Release preparation → Production

Advantages

Disadvantages

When to Use

Avoid very long-running feature branches. If a change is large, break it into incremental slices or use branch-by-abstraction so you can merge to trunk early and often.

Critique

Forking

In a fork-based workflow, contributors work on their own copy of the repository—a fork—instead of pushing branches to the canonical project. Changes flow back to the upstream repository via pull requests (PRs; “merge requests” on some platforms), where maintainers review, discuss, and merge.

Typical fork setup:

Upstream repo
   │
   ├──▶ main (production)
   │       │
   │       └──▶ (optional) topic branches
   │
   └──▶ Forked repo (contributor / team)
           │
           ├──▶ main (kept in sync with upstream)
           │
           └──▶ feat/XYZ-topic
                     │
                     ▼
                Development & local CI
                     │
                     ▼
                 Pull request ▲
                               │
                               ▼
                  Review → Merge → Upstream main

Advantages

Disadvantages

When to Use

Keep forks fresh by adding the upstream remote (git remote add upstream <url>), then regularly syncing: git fetch upstream followed by git rebase upstream/main (or git pull --rebase upstream main). Stale forks are the main pain point here; proactive syncing and small, focused PRs keep the workflow smooth.

Critique

Git Flow

Git Flow is a prescriptive branching model, proposed by Vincent Driessen, that assigns named roles to branches with clear rules for when to create, merge, and retire them. It suits projects that ship versioned releases on a predictable cadence and need to patch production urgently while regular feature work continues.

main ──┬─────────────▶ (tag vX.Y.0) ──┐
       │                              │
       │◀─ merge hotfix/* ──────▶ (tag vX.Y.1)
       │                              │
develop│◀───────────── merge release/*┘
  │
  ├──▶ feature/ABC-123
  │        │
  │        └──▶ merge → develop
  │
  └──▶ release/X.Y
           │
           ├──▶ final bug fixes
           └──▶ merge → main  &  merge → develop

Advantages

Disadvantages

When to Use

If you aim for continuous delivery or deploy many times a day, Git Flow will likely feel heavyweight; consider trunk-based development or a simple feature-branch workflow instead.

Critique

Environment Branching

In an environment-branching workflow, each runtime environment—development, QA, staging, production—has its own long-lived branch. Code moves “up the ladder” by merging (or cherry-picking) from one environment branch to the next, mirroring how build artefacts and database changes are promoted.

Typical branch mapping:

develop ──┬──────────▶ (dev environment)
          │
          └──▶ qa ────┬────────▶ (QA / test environment)
                      │
                      └──▶ staging ───▶ (staging environment)
                                          │
                                          ▼
                                      main (prod) ──▶ (production)

Promotion flow:

  1. Finish work on develop → merge to qa.
  2. QA passes → fast-forward or merge qastaging.
  3. Final sign-off → merge stagingmain and deploy. Hotfixes start on main, then cascade back to staging, qa, and develop to keep branches aligned.

Advantages

Disadvantages

When to Use

If rapid, continuous delivery is the goal, consider slimming the number of environment branches—or switch to release branches or trunk-based development plus feature flags—to keep promotion fast while retaining control.

Critique

Common complaints about this model include:

These critiques show up across CD/GitOps guidance and are a big reason many call “branch-per-environment” an anti-pattern.

Table of Contents

    Strategies for Branching
    1. Trunk-Based Development
      1. Advantages
      2. Disadvantages
      3. When to Use
      4. Critique
    2. Release Branches
      1. Advantages
      2. Disadvantages
      3. When to Use
      4. Not the same as Git Flow
      5. Critique
    3. Feature Branches
      1. Advantages
      2. Disadvantages
      3. When to Use
      4. Critique
    4. Forking
      1. Advantages
      2. Disadvantages
      3. When to Use
      4. Critique
    5. Git Flow
      1. Advantages
      2. Disadvantages
      3. When to Use
      4. Critique
    6. Environment Branching
      1. Advantages
      2. Disadvantages
      3. When to Use
      4. Critique