Skip to content

Diff Rows And Files

Graft has two diff layers:

  • repository diffs compare paths in the app-state tree
  • row diffs expand modified SQLite database snapshots into table and row changes

Use repository diffs to answer “which app-state paths changed?” Use row diffs to answer “which SQLite rows changed?”

Terminal window
graft diff
graft diff --json

Compare staged changes:

Terminal window
graft diff --staged
graft diff --json --staged

Filter by content kind:

Terminal window
graft diff --kind sqlite_database
graft diff --kind text_file
graft diff --kind binary_file
Terminal window
graft diff HEAD~1 HEAD
graft diff HEAD~1 HEAD data.sqlite
graft diff --json HEAD~1 HEAD

Path-level output reports each changed path, its change type, kind, and storage.

Add --rows for SQLite database paths:

Terminal window
graft diff --rows HEAD~1 HEAD data.sqlite
graft diff --json --rows HEAD~1 HEAD data.sqlite

With JSON output, database entries can include row changes, schema changes, capabilities, limitations, and a logical_status.

Common logical statuses:

StatusMeaning
logical_changesSupported row or schema changes were found.
unsupported_logical_surfaceSQLite changed in a way Graft cannot fully interpret.
file_changed_no_supported_logical_changesThe file changed, but supported logical rows and schema have no net change.
row_diff_unavailableRow diff was not available for that file.

This transcript was captured from a real graft run. Hashes and timestamps will differ on your machine.

Terminal window
$ graft diff --rows HEAD~1 HEAD app.sqlite
Row Diff 55c99f73d879..d5cb39df069b
modified: app.sqlite
Diff LSN 2 -> 4
============================
Table 'tasks': +1 inserts ~1 updates
~ rowid 2:
old: [Null, Text("record cli output"), Text("open")]
new: [Null, Text("record cli output"), Text("blocked")]
+ rowid 4: [Null, Text("publish docs"), Text("open")]

Comparing two branches shows the row changes needed to transform main into feature/progress:

Terminal window
$ graft diff --rows main feature/progress app.sqlite
Row Diff d5cb39df069b..89abefbeb063
modified: app.sqlite
Diff LSN 4 -> 4
============================
Table 'tasks': +1 inserts -1 deletes ~2 updates
- rowid 4: [Null, Text("publish docs"), Text("open")]
~ rowid 2:
old: [Null, Text("record cli output"), Text("blocked")]
new: [Null, Text("record cli output"), Text("open")]
+ rowid 3: [Null, Text("add screenshots"), Text("open")]
~ rowid 1:
old: [Null, Text("write quickstart"), Text("open")]
new: [Null, Text("write quickstart"), Text("done")]

Use path summaries for navigation and row payloads for detail panes:

Terminal window
graft diff --json --rows HEAD~1 HEAD data.sqlite

Suggested UI treatment:

StateUI
file changed and logical_changesShow table, row, and schema changes.
file changed and file_changed_no_supported_logical_changesShow as file-level change or logical no-op.
unsupported_logical_surfaceShow a caveat and keep a conservative review path.
binary file changedShow file-level metadata and allow open/replace/download.

Low-level LSN diffs are documented under Snapshot Storage And LSNs for storage debugging. Normal user-facing history should use repository commits and revspecs.