A diff that changes different fields on the same resource can be merged. A diff that changes the same field on the same resource cannot — that is a merge conflict, and pretending it is not produces silent data corruption. FHIR-aware merge tooling has to know the difference. Getting the rule right prevents the "we lost that update" incidents that come from over-permissive merges. The site's Resource-vs-resource comparator is the pre-flight for merge decisions. For the wider FHIR framing, the behavioral health interoperability hub has more.
The Simple Case
- Branch A changes
Patient.name[0].family - Branch B changes
Patient.birthDate
Different fields. Auto-mergeable. The resulting resource has both changes.
The Conflict Case
- Branch A changes
Patient.name[0].familyfrom "Smith" to "Jones" - Branch B changes
Patient.name[0].familyfrom "Smith" to "Brown"
Same field. Same base. Two divergent values. There is no correct merge — a human has to decide.
Auto-mergers that pick one (last-write-wins, or diff-fanciest-wins) silently discard the other change. That is data loss.
The Semantically-Equal Case
- Branch A changes
Patient.genderfrom "male" to "female" - Branch B changes
Patient.genderfrom "male" to "female" (from a different upstream)
Same field. Same target. Semantically the same change from different sources. Auto-mergeable — take either version.
Merge tools that flag this as a conflict produce noise. FHIR-aware merge tools detect the semantic equality.
For the semantic vs structural framing, structural diff vs semantic diff for FHIR JSON is the entry (via the earlier articles in this silo).
The Array Case
- Branch A adds an identifier
- Branch B adds a different identifier
The array grew on both sides. Both identifiers should end up in the merged result. That is not a conflict — it is a union merge.
Array-of-identifier merges usually want union. Array-of-name merges are more ambiguous (usually you want both, but sometimes only one is "official").
The Reference Case
- Branch A rewrites
Observation.subjectfrom Patient/123 to Patient/456 - Branch B rewrites
Observation.subjectfrom Patient/123 to Patient/789
Both branches redirected the reference. That is a conflict — a human has to decide which patient the observation should reference.
Reference conflicts are often the highest-stakes merge conflicts. Do not auto-resolve.
For the PATCH generation side that this merge policy consumes, PATCH generation from a JSON diff is the entry.
The meta.profile Case
- Branch A changes
meta.profileto add a new profile - Branch B changes
meta.profileto add a different new profile
The profile array grew on both sides. Union merge is usually correct. But if the profiles conflict semantically (different Patient IGs), a human should review.
The Bundle.entry Case
Two branches added different entries to a Bundle. Usually a union merge. But if entries have conflicting fullUrls, that is a real conflict.
For the alignment mechanic that pairs with this, diffing Bundles: aligning entries before comparing is the entry.
What A Good Merge Tool Does
- Auto-merges disjoint field changes
- Detects semantic equality across branches
- Union-merges array additions where semantically safe
- Flags same-field divergence as conflict
- Flags reference conflicts as high-priority
- Preserves audit trail of both branches' changes
Every criterion is a design choice. Skipping any produces silent data loss or noisy false positives.
Cross-Version Merges Deserve Attention
Merging a change from an R4 branch into an R5 branch is not a simple diff-merge — it is a version migration. For the mechanic, diffing across FHIR versions (R4 to R5) is the entry.
The Short Version
Disjoint changes auto-merge. Same-field divergence is a conflict. Semantic equality is not a conflict even if bytes differ. Array additions are usually union. Reference conflicts always escalate. FHIR-aware merge tools detect these categories; naïve diff-mergers do not.

Sources
- HL7 canonical FHIR references chapter - HL7 canonical FHIR references chapter
