Skip to content

feat: Semantic diff and three-way merge for .tm7 deconfliction#17

Merged
Hacks4Snacks merged 5 commits into
mainfrom
hacks4snacks/gitdeconfliction
Jul 7, 2026
Merged

feat: Semantic diff and three-way merge for .tm7 deconfliction#17
Hacks4Snacks merged 5 commits into
mainfrom
hacks4snacks/gitdeconfliction

Conversation

@Hacks4Snacks

Copy link
Copy Markdown
Owner

feat: semantic diff and three-way merge for .tm7 deconfliction

What & why

.tm7 is DataContractSerializer XML which is verbose and order-sensitive so git's line-based
merge corrupts it (conflict markers break deserialization) and its diffs are unreadable.
This adds a structural, identity-aware diff and merge keyed by the stable per-node GUID every
model already carries, exposed via the CLI, wired into git, and surfaced in Studio so .tm7
becomes reviewable and mergeable in normal branch/PR workflows.

Highlights

  • Diff/merge core (Editing): geometry-free, GUID-keyed ModelSnapshot/ModelDiff and
    ModelMerge. Non-overlapping edits combine; genuine conflicts (same-property divergence,
    delete/modify, dangling connector) resolve to ours and are reported, the written model is
    always valid, never marker-laced. Falls back to a two-way merge when the common ancestor
    isn't available.
  • CLI: tmforge diff <a> <b> [--json] and tmforge diff --textconv (readable git diffs);
    tmforge merge <base> <ours> <theirs> shaped as a git driver (writes a <path>.conflicts.json
    sidecar + non-zero exit on conflict); tmforge git-setup [--global] [--print] wires the
    diff/merge drivers with no committed .gitattributes required.
  • Git integration: .gitattributes (*.tm7 diff=tmforge merge=tmforge) + textconv/merge-driver
    config; fully opt-in, so git behaves exactly as before until configured.
  • Engine/API/WASM: shared EngineService.Merge (nullable base -> two-way) behind
    POST /v1/model/merge and the in-browser WASM Engine.Merge; OpenAPI v1.json regenerated.
  • Formats: tmforge-json read now preserves GUID element and surface ids, so identity
    survives the round-trip and pages align across files (also makes diff meaningful on .tmforge.json).
  • Studio: a Merge toolbar button opens a resolve modal — upload ours/theirs (base optional),
    pick ours-or-theirs per conflict, then load onto the canvas or download .tm7; app-styled file pickers.
  • Tests: diff / snapshot / merge unit tests (Editing), CLI diff / merge / git-setup tests, engine
    merge tests, and id-preservation coverage; validated with real git merge and in-browser WASM smokes.
  • Docs: cli-reference, studio-guide, and README updated.

@Hacks4Snacks Hacks4Snacks merged commit cf608a0 into main Jul 7, 2026
6 checks passed
@Hacks4Snacks Hacks4Snacks deleted the hacks4snacks/gitdeconfliction branch July 7, 2026 23:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant