Why Long-Lived Branches Are Often Necessary in Salesforce Projects

Trunk-based development sounds like a DevOps ideal, but in Salesforce the reality is more nuanced. Here's why long-lived branches still matter and how to manage them thoughtfully.

5 min readDevOps Strategy

# LONG-LIVED BRANCHES

Strategic Question
Do you need dev?
Integration required?
UAT handoff?
Prod deploy?
Minimal Branches
skip dev?
int
preprod
main
✅ Only when environment strategy demands it

Trunk-based development sounds like a DevOps ideal. But in Salesforce? The reality is more nuanced. Here's why long-lived branches still matter — and how to manage them thoughtfully.


If you've read our earlier piece on Why Trunk-Based Development Doesn't Quite Work for Salesforce, you already know the limitations. Metadata friction. Sandbox statefulness. No clean build artifacts. No truly repeatable environments.

All of this sets the stage for a branching strategy that's more grounded — and more realistic — for the Salesforce platform.

Which brings us here: Let's talk about long-lived branches — what they are, why they're used, and how to avoid going overboard.


It Starts with Environments — Not Branches

In most Salesforce implementations, you don't begin with Git branching strategy. You begin with environment strategy.

And the environment layout almost always looks like this:

  • Developer sandboxes (individual or shared)
  • Integration sandbox (INT)
  • Pre-production/UAT sandbox (PREPROD or UAT)
  • Production

Why do we need these?

Because the feature lifecycle in Salesforce is messy. You can't simply "build once, deploy everywhere." There's no artifact. Every change is a metadata delta. And different devs push different features on different timelines.

So here's what each environment does:

🔧 Integration (INT)

Where all feature work first comes together. Different stories, different developers — merged and tested to ensure nothing breaks when features meet each other for the first time.

👩‍💼 Pre-Prod / UAT

The closest replica to production. Often loaded with full or partial production data to test scale, edge cases, UI behavior, and business workflows in a high-fidelity sandbox.

This is where business stakeholders validate:

"Does it look and behave as expected — under real-world data conditions?"


So Where Do Long-Lived Branches Come In?

Every one of those environments needs to be stable.

You can't afford to have a dev pushing half-complete changes into UAT. You can't risk overwriting someone else's integration work. You need isolation — per environment.

That's where Git comes in.

Most teams adopt a 1:1 mapping between Git branches and Salesforce environments:

  • dev branch → developer sandbox
  • int branch → integration sandbox
  • preprod branch → pre-prod or UAT
  • main branch → production

These are long-lived branches — they stick around for the entire project lifecycle and serve as source-of-truth references for their corresponding sandboxes.

You could, in theory, run everything off main. But as we discussed in our trunk-based development piece, unless you have:

  • Fully automated deployments
  • Environment spin-up on demand
  • Feature flag infrastructure
  • Clear rollback plans

…that becomes extremely fragile. Most backend teams don't even do that — and in Salesforce, it's far harder.


How Many Long-Lived Branches Do You Really Need?

This is the strategic question.

Yes, you could maintain:

  • A dev branch
  • An int branch
  • A uat or preprod branch
  • And a main branch for prod

But every new long-lived branch adds friction:

  • More PRs
  • More rebasing
  • More merge conflicts
  • More chances to miss a critical delta

So the golden rule is:

Only introduce long-lived branches when your environment strategy demands it.

Ask yourself:

  • Can you live without a long-lived dev branch?
  • Can developers push to individual feature branches instead, and merge straight to int?
  • Can you consolidate integration testing into preprod?
  • Or can you do integration testing by having a common dev box itself?

The fewer long-lived branches you maintain, the simpler your Git hygiene becomes — and the lighter the burden on release managers, developers, and QA alike.


The DevOps Tool Trap

Some DevOps tools claim to make individual dev boxes a paradise — with all the back-retrofitting, metadata sync, and environment management built right into their platform.

But here's what they conveniently sidestep: Do you even really need individual dev branches? Or even a common dev branch?

These tools will proudly tell you they "support any branching approach" — and then leave you to determine which branching strategy to use. They sideline the core importance of branching strategy entirely.

The question isn't whether your tool can handle complex workflows. The question is: Should you create that complexity in the first place?


Trend Toward the Ideal: Fewer Branches

Here's the mindset shift:

Try to live with as few long-lived branches as possible.

The ideal would be just one long-lived branch: main. Of course, you can't achieve that in most Salesforce contexts.

So architect your branching strategy with ideally just one more long-lived branch: preprod.

If you absolutely must go for individual dev boxes and need an integration sandbox, then maybe add another long-lived integration branch.

But resist the urge to create dev, qa, uat, staging, and release branches just because your org chart has those environments.

Each branch is debt. Minimize the debt.


TL;DR

Trunk-based development may be a noble goal — but for most Salesforce projects, long-lived branches are the pragmatic reality.

The key is not to avoid them, but to manage them intentionally:

  • Align branches 1:1 with real orgs
  • Limit the number to reduce merge chaos
  • Don't treat Git branching as policy — treat it as reflection of process
Tags:SalesforceDevOpsGitBranching StrategyCI/CDEnvironment Management