Start free
Andrew Hanna

Andrew Hanna

How to resolve Salesforce metadata merge conflicts without losing anyone's work

How to resolve Salesforce metadata merge conflicts without losing anyone's work

Short answer: Most Salesforce merge conflicts are not real disagreements. They are two people adding unrelated things to the same oversized XML file, or the same elements coming back in a different order. Combine both sides for additive metadata like profiles, permission sets, layouts and labels, and never hand-merge generated XML like Flows: pick one version and re-apply the other change in Flow Builder.

Why are Salesforce merge conflicts different from ordinary code conflicts?

Four platform quirks cause almost all of them.

  • Element order is not guaranteed. The Metadata API can return the same file with its elements in a different sequence, so Git reports a conflict where nothing changed. These are false conflicts.
  • Some types are one giant file. A profile carries object, field, Apex class and page permissions in a single document. Two people on unrelated features write to the same lines.
  • Some XML is machine generated. A Flow definition holds canvas coordinates and generated element names. It is not meant to be edited by hand and it is not safe to merge by hand.
  • Git resolves text, Salesforce validates meaning. A textually clean merge can still produce a file the deployment rejects, or a valid file that silently drops somebody's permission.

Which metadata types conflict most, and what do you do about each?

Profiles and permission sets

The worst offenders, and almost always additive. Two branches each add an objectPermissions or fieldPermissions block and the additions land next to each other. Take both sides, then de-duplicate on the key element (field, object, apexClass) and re-sort. Never resolve a profile by accepting one side wholesale.

Worth knowing: Salesforce has cancelled the retirement of permissions in profiles (Salesforce Help article 003834041), so profiles are not going away on a clock and this problem does not solve itself. Salesforce still recommends a least-privilege model built on permission sets, and moving permissions off profiles genuinely shrinks the conflict surface, because permission sets are small, per-feature files.

Flows

Do not hand-merge them. The XML carries generated element names and canvas coordinates, so a line-level merge produces something that looks plausible and behaves wrongly. Choose one version as the winner and re-apply the other change in Flow Builder.

Page layouts and Lightning record pages

Layout XML lists every item in position order, so two people adding fields to different sections still collide if the sections are adjacent. Combine both sides, then check that every layoutItem from each parent survived. If a Lightning record page conflict runs to more than a few lines, rebuild it in the Lightning App Builder rather than merging it.

Custom objects and fields

If your repo stores an object as one file, every field change touches it. Decomposed source format gives each field its own file and removes most of these conflicts before they happen.

Apex classes and triggers

Treat these as normal code conflicts, because they are. Resolve the logic, re-run the tests, and then check that the class is still granted in the profiles and permission sets that reference it.

Custom labels and translations

Single alphabetical files, purely additive. Take both sides and re-sort.

How do you read a Salesforce metadata diff before resolving anything?

  1. Confirm which side is which. In a merge, "ours" is the target branch and "theirs" is incoming. In a rebase they swap. Getting this backwards is the most common way work disappears.
  2. Filter out ordering-only differences. If both sides hold the same elements in a different sequence, nobody changed anything.
  3. Hunt for deletions, not additions. Additions are usually safe to combine. A block that exists on one side and not the other is the change that costs someone a day.
  4. Compare against the target org, not only the branch. Somebody may have edited the org directly since the branch was cut.
  5. Validate before you merge the pull request. XML that merges cleanly can still fail deployment validation.

How do you resolve a profile conflict without deleting a colleague's permission?

  1. List the conflicting blocks by their key element rather than by line number.
  2. Keep both sides of every block that appears on only one side.
  3. Where the same key appears on both sides with different values, decide permission by permission and record the reasoning in the pull request.
  4. Remove the conflict markers and re-sort the file so the next diff stays small.
  5. Validate the merged file against the target org.
  6. Ask both authors to confirm their permission still exists after the merge. This takes a minute and catches what review misses.

How do you resolve a Flow conflict safely?

  1. Take the version already on the target branch as the base and discard the other side in Git.
  2. Open a sandbox that has that base version and re-apply the second author's change in Flow Builder.
  3. Retrieve the flow and commit the retrieved file as the resolution.
  4. Check which version is active in the target org before deploying, because deploying a flow adds a version rather than replacing one.

How do you stop the next conflict?

  • Short-lived branches, merged the same week they are cut.
  • One feature per pull request.
  • Permissions in per-feature permission sets instead of shared profiles.
  • Objects stored in decomposed source format.
  • Pull the target branch into yours before opening the PR, so you resolve on your own time with your own change fresh in mind.

This guide is part of our Salesforce DevOps guides.

FAQ

Can Git resolve Salesforce metadata conflicts on its own?

Only textually. Git cannot tell that two profile blocks are independent or that a reordered file is unchanged, so it raises false conflicts and will happily accept a merge that is semantically wrong.

What is a false conflict?

A conflict where both sides hold the same metadata in a different order. The Metadata API does not guarantee element order, so two retrievals can differ with no real change behind them.

Should I ever hand-edit Flow XML to resolve a conflict?

No. Pick one version and re-apply the other change in Flow Builder, then commit what you retrieve.

Why do profiles conflict when we worked on completely different features?

A profile is a single file covering permissions for every object, field and class in the org, so unrelated features end up writing to adjacent lines.

How do I check the merge did not lose anything?

Diff the merged file against both parent versions, confirm every key element from each side survived, and validate the deployment against the target org before merging.

Related Articles

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

Commitment free!