Start free
Andrew Hanna

Andrew Hanna

Git branching strategies for Salesforce teams: a decision rule

Git branching strategies for Salesforce teams: a decision rule

TL;DR: Pick your branching model from two inputs, team size and sandbox topology, and nothing else. Under about four contributors with only developer sandboxes, use one main branch and short-lived feature branches. Between four and ten with a partial copy for UAT, add a release branch per release and stop there. Above that, or with a full sandbox and a fixed change window, GitFlow earns its ceremony. Branch per environment is a compliance choice, not an engineering one.

What does a branching strategy actually decide?

Three things, and only three: where work in progress lives, how a change is promoted to the next environment, and what has to be true before something reaches production. Everything else is diagram decoration.

Salesforce teams get this wrong because the general engineering advice assumes something that is not true on the platform: that a branch gives you somewhere to run it.

What are the three models in plain terms?

Trunk-based with short-lived feature branches

One long-lived branch, main, that always reflects what production should be. Feature branches live days, not weeks, and merge back through a pull request. Fewest moving parts, fewest conflicts, hardest discipline.

GitFlow

main for released code, develop for integrated work, plus release and hotfix branches. Built for scheduled releases and for maintaining a live version while the next one is being built. It costs you an extra permanent branch and a lot of merging.

Branch per environment

One branch mirroring each org: dev, UAT, staging, production. It is usually the first thing teams build, because it looks like the org landscape they already have. Promotion becomes a merge between environment branches, which sounds tidy and turns into merges of merges plus routine cherry-picking.

Which Salesforce constraints break the textbook advice?

This is where most branching articles stop and where the real decision lives.

  • A branch does not give you an org. Environments are scarce and slow. Salesforce sets minimum refresh intervals of one day for Developer and Developer Pro, five days for Partial Copy and 29 days for Full. The number of long-lived branches you can genuinely test is capped by your sandbox count, not by your Git skills.
  • Metadata is retrieved, not authored. Admins change things in an org and someone pulls it later. A long-lived branch cannot be reconciled against declarative work that never entered Git in the first place.
  • Some things have no branch at all. Org-wide defaults, licences, certain configuration and all record data live outside the repo. A model that assumes every environment difference is in Git will quietly lie to you.
  • There are no feature flags for clicks. Trunk-based development in normal engineering leans on toggles to merge unfinished work. Declarative config often has no toggle, so the Salesforce equivalent is to deploy the metadata and withhold the permission set assignment until go-live.
  • Merge cost is asymmetric. Profiles, permission sets and layouts conflict far worse than Apex. Every extra week a branch lives multiplies that cost, which pushes Salesforce harder toward short branches than typical software.

So what is the decision rule?

  1. One to three contributors, developer sandboxes only, no fixed release date. Main plus short-lived feature branches. Anything more is ceremony you will abandon in month three.
  2. Four to ten contributors, a partial copy for UAT, releasing every sprint. Main, short-lived feature branches, and one release branch cut per release. Resist adding a permanent develop; you do not have the sandbox count to justify it.
  3. More than ten contributors, or a full sandbox, or a fixed change window, or you must patch the live release while building the next. GitFlow. The ceremony is now buying you something real.
  4. Package and ISV teams. Branch by package version, not by environment. Your release unit is the package version and your test bed is a scratch org, so environment branches model the wrong thing entirely.
  5. Branch per environment. Justified when a branch has to be an auditable mirror of an org's state, which is a regulatory requirement rather than a delivery preference. Go in knowing the cost: cherry-picking becomes routine and drift becomes invisible.

Notice that release cadence barely appears. Cadence is an output of your sandbox topology, not an independent input, and teams that pick a model by desired cadence end up with a process their environments cannot support.

How do you move off branch per environment without a big bang?

  1. Stop creating new environment branches today. The model stops growing before it starts shrinking.
  2. Reconcile main with production and treat the diff as a real backlog, not a curiosity. It is usually where the surprises are.
  3. Turn environment branches into deployment targets in the pipeline instead of Git branches. The environment still exists, it just stops being a place code lives.
  4. Cap feature branch age at one sprint. Anything longer needs a package boundary or a permission gate, not a longer branch.
  5. Keep exactly one release branch, and only if you genuinely support a live release while building the next.

Making the model stick

The model that survives contact with a real team is the one the pipeline enforces, not the one in the onboarding doc. If a consultant has to remember the branching rules, the rules will be broken during the first busy release week. Serpent runs a ticket-based workflow with Git in the background, so the branch, the pull request and the promotion path come from the ticket rather than from memory. More pipeline guides live in our SF Guides library.

FAQ

Is trunk-based development realistic for a team of admins?

Yes, and it is usually easier for admins than GitFlow, because there is one branch to understand. The discipline that matters is short branches, not Git fluency.

Do we need one Git branch per sandbox?

No. A sandbox is a deployment target. Mapping one branch to each org is the main cause of merges of merges and permanent cherry-picking.

How long should a Salesforce feature branch live?

Days. One sprint is the outer limit. Beyond that, metadata drift and profile conflicts cost more than the branch saves.

How do hotfixes work under trunk-based?

Branch from the last released commit, fix, validate, deploy, then merge back into main immediately so the fix is not lost on the next release.

Does the model change for 2GP package teams?

Yes. Branch by package version and test in scratch orgs. Environment branches model an org landscape that a package team does not release into.

Related Articles

Curious about faster shipping before you dive in? Let's talk

Commitment free!