Learn/Semantic · 6 min · updated 2026-08-03

AST merge and text merge: why some conflicts should not exist

Git merges lines, so two agents editing different functions in the same region can conflict for no semantic reason. What a structural merge resolves, and what it cannot.

A text merge asks whether two changes touched the same lines. A structural merge asks whether they touched the same code. Those give different answers often enough to matter, in both directions.

The false conflict

Two agents add a method to the same class. One adds it after the constructor, the other adds it in the same place. The methods are unrelated and both should exist. Git sees two different insertions at one line offset and raises a conflict, which someone then resolves by hand, correctly, in the only way it could have been resolved. Structural merge places both children under the class node and produces the obvious result.

The false clean merge

The opposite case is worse. One branch changes the signature of a function; another branch adds three calls to the old signature in a different file. Git merges cleanly because the lines never met. The build breaks, and if the language is dynamically typed it does not break until it runs. A structural merge that carries a dependency graph can see the mismatch, because it knows the callers of the function that changed.

CaseText mergeStructural merge
Two methods added to one classConflictBoth kept
Same function edited on both sidesConflictConflict, correctly
Reformat on one side, edit on the otherConflict across the fileOnly the edited node
Signature changed, callers added elsewhereClean, and brokenReported as an impact

What a structural merge cannot do

It cannot decide semantics. If both sides changed the body of the same function, there is a real conflict and a person has to choose. It also cannot merge across languages it has no grammar for, and it inherits every ambiguity of the parse. The honest claim is narrower than the marketing usually made for it: structural merging removes a category of conflict that never had meaning, and surfaces a category of breakage that used to merge silently.

How Aura uses it

Aura does not replace git merge. It works at the node level for two specific operations. The first is rewind: reverting a single function to a previous state without touching the rest of the file, which avoids the conflict a revert would otherwise cause. The second is applying a teammate's changed function into your working copy at the AST level rather than as a patch, so an unrelated local edit in the same file does not collide.

The rest of the workflow stays ordinary Git, which is the point: Aura is Git plus a semantic index, not a replacement for it. See also collision detection, which tries to prevent the conflict before either agent writes.

Questions

What is an AST merge?

A merge that combines two versions by their parsed structure. Changes to different functions are independent no matter how close together they sit in the file, so edits that a line-based merge reports as a conflict are simply applied.

Why does Git report conflicts when the changes are unrelated?

Git merges hunks of lines. Two edits inside the same few lines are a conflict even when one changed a function and the other changed the function beneath it. The overlap is textual; the code has no disagreement to resolve.

Can a structural merge resolve every conflict?

No, and it should not. It removes conflicts that are only artefacts of line proximity. Two branches that genuinely change the same function in different ways still disagree, and that disagreement is real information a person needs to settle.