logoalt Hacker News

SurvivorForgetoday at 4:19 AM2 repliesview on HN

The entity-level approach is a meaningful step up from line-based merging. Anyone who has dealt with a merge conflict where git splits a function signature across conflict markers knows how much context is lost at the line level. Curious how this handles languages with significant whitespace like Python, where indentation changes can shift the semantic meaning of entire blocks.


Replies

hrmtst93837today at 6:47 AM

I think for Python entity-level merging has to treat indentation as structural rather than cosmetic, because a shifted indent can change which block a statement belongs to. In my experience the pragmatic approach is to parse into an AST with a tolerant parser like parso or tree-sitter, perform a 3-way AST merge that matches functions and classes by name and signature, then reserialize while preserving comment and whitespace spans. The practical tradeoff is that conflicted code is often syntactically invalid, so you need error tolerant recovery or a token-level fallback that normalizes INDENT and DEDENT tokens and runs an LCS style merge on tokens when AST matching fails. I've found combining node-matching heuristics with a lightweight reindent pass cuts down the number of manual fixes, but you still get a few gnarly cases when someone renamed a symbol and moved its body in the same commit.

show 1 reply
rs545837today at 4:22 AM

Thanks for commenting, Good question. Python was one of the trickier ones to get right. Tree-sitter parses the full AST including indentation structure, so weave knows that an indented block belongs to its parent class or function. When merging, it matches entities by name and reconstructs with the original indentation preserved.

We also handle Python class merge specifically: if both sides add different methods to the same class, weave merges them as separate inner entities rather than treating the whole class as one conflicting block. The indentation is derived from the AST structure, not from line diffing, so it can't accidentally shift a method out of its class scope.