Field-level merge shrinks what humans have to resolve
Aliases: per-column merge · structural merge · less human
What it is
Inside one record, name, date, cover, notes are different fields. Two sides each changed a different field; scoring a conflict on the whole record sends coexistable edits to a human. Field-level merge shrinks the conflict unit from “this whole row” to “the few fields that actually forked”. Fields that did not fork keep both sides’ writes; people only handle the cells that really collided.
This leaf is the gain side of merge grain: once the data is structured, the span of human intervention can shrink. It does not argue how dangerous last-write-wins is — that is another verdict. The verdict here is “merge the fields that can merge first”.
Why it happens
A conflict is two non-commutative writes to the same address. The larger the address, the likelier two writes fall into it. Shrink the address from document to field and the two writes often land on different addresses: one person the due date, the other the assignee — two addresses, two commutative writes, merge is juxtaposition. The number of times a person is called drops not because conflicts vanished, but because many “conflicts” were misdrawn boundaries.
Structure is the premise. Fields need a stable identity (this is due date, that is assignee), not “that blob of bytes on the left”. Identity tells the merge function which two cells to compare. A blob without identity can only be compared as a pack; field-level has nothing to talk about. The merge function is independent per field: same, take; different, mark conflict. The record’s shell (primary key, version) still has to express “this record had a partial conflict”, or the UI can only paint the whole row red or green.
Where it stops holding
When fields share an invariant (start must not be after end, amount must equal the sum of lines), auto-merging each field can assemble an illegal record. The conflict unit then rises to the group the constraint lives on, rather than clinging to one cell. List-shaped fields (tags, several assignees) are really element-level: add A and add B merge; add A and delete A still conflict. Treating the list as one string field turns a mergeable add into a prose conflict. Computed and derived values do not participate; they recompute after the base fields merge. A permission field auto-merged as “union of both sides’ rights” may widen access; those fields often promote to must-human.
Applying it
- Give every user-editable record a field table; merge walks fields. Only fields whose values forked are marked pending.
- While some fields are pending, the record remains readable on already-merged fields. Do not lock the whole row.
- Pack cross-constrained fields into one merge unit and say on the UI that they are a group.
- How to check: two people open the same task card; one changes due date, the other the title. After sync, no one should have to tap Resolve; both edits are there. Then both change the same due date: only the date cell enters conflict; description, title, attachments must not be swept in. If the whole card goes red, grain is still at record level.
Related
- Same group: I3.11.2 Free text generally cannot be merged by the system · I3.11.3 Finer merge grains win more automatic merges and cost more complexity · I3.11.4 A merge UI must show where each difference came from, not only the result
- Nearby: I3.04 Sync conflicts · I3.13 State-machine completeness and illegal states
- Search terms:
field-level merge·structural merge·conflict granularity