How Graph Diffing Compares Snapshots Over Time in Code-Review-Graph
Graph diffing in code-review-graph captures the state of a SQLite-backed knowledge graph as JSON snapshots and compares them using deterministic set operations to identify added or removed nodes, edges, and community reassignments.
The code-review-graph library stores your entire codebase as a structured knowledge graph using SQLite. To track how this graph evolves across commits or releases, the library provides a specialized graph diffing system that lets you take point-in-time snapshots and precisely compare them to reveal structural changes between any two states.
How Graph Diffing Works in Code-Review-Graph
The graph diffing implementation resides in code_review_graph/graph_diff.py and operates through four distinct phases: capturing the current state, serializing it to disk, reloading it later, and performing set-based comparisons.
Taking a Snapshot of Graph State
The take_snapshot(store) function extracts the complete state from a GraphStore instance. According to the source code in graph_diff.py (lines 15-43), it collects:
- Global statistics via
store.get_stats()for total node and edge counts - All nodes via
store.get_all_nodes(exclude_files=False)with their qualified names, kinds, file paths, and community assignments - Community mappings via
store.get_all_community_ids()
The function returns a dictionary containing node_count, edge_count, a nodes mapping (qualified name to metadata), and an edges set containing strings in the format source→target:kind.
Persisting Snapshots to Disk
The save_snapshot(snapshot, path) function (lines 46-53 in graph_diff.py) serializes the snapshot dictionary to JSON. To ensure deterministic output, edge sets are converted to sorted lists before dumping, making file comparisons and version control diffs predictable.
Loading Saved Snapshots
The load_snapshot(path) function (lines 56-61) reverses the process by reading the JSON file and converting edge lists back into Python sets for efficient comparison operations.
Computing Diffs Between Snapshots
The diff_snapshots(before, after) function (lines 64-122) performs the actual comparison using set arithmetic:
- Node comparison: Converts the
nodesmapping keys from both snapshots into sets (before_nodesandafter_nodes), then calculatesnew_nodes = after_nodes - before_nodesandremoved_nodes = before_nodes - after_nodes - Edge comparison: Performs analogous set differences on the
before_edgesandafter_edgessets - Community tracking: For nodes present in both snapshots, compares community IDs and records any changes with the node name, previous ID, and new ID
The result dictionary contains:
new_nodesandremoved_nodes(limited to 100 entries each)new_edgesandremoved_edges(limited to 100 entries each)community_changes(limited to 50 nodes)summarywith counters fornodes_added,nodes_removed,edges_added,edges_removed,community_moves, and total node counts before/after
Practical Example: Tracking Code Evolution
Here is a complete workflow for using graph diffing to compare snapshots over time:
from pathlib import Path
from code_review_graph.graph import GraphStore
from code_review_graph.graph_diff import take_snapshot, save_snapshot, load_snapshot, diff_snapshots
# 1️⃣ Open a graph (assumes a built graph at .code-review-graph/graph.db)
store = GraphStore(Path(".code-review-graph/graph.db"))
# 2️⃣ Take a snapshot of the current state
snap_before = take_snapshot(store)
# 3️⃣ Persist the snapshot – useful for later comparison or CI storage
save_snapshot(snap_before, Path("snap_before.json"))
# … make code changes, rebuild the graph, or run another analysis …
# 4️⃣ Take a second snapshot after the changes
snap_after = take_snapshot(store)
save_snapshot(snap_after, Path("snap_after.json"))
# 5️⃣ Load snapshots (if they were stored on disk)
snap_before = load_snapshot(Path("snap_before.json"))
snap_after = load_snapshot(Path("snap_after.json"))
# 6️⃣ Compute the diff
diff = diff_snapshots(snap_before, snap_after)
print("Added nodes:", diff["new_nodes"])
print("Removed edges:", diff["removed_edges"])
print("Community moves:", diff["community_changes"])
print("Summary:", diff["summary"])
Summary
- Graph diffing in code-review-graph relies on deterministic JSON snapshots captured via
take_snapshot()and compared viadiff_snapshots(). - The algorithm uses simple set operations (difference) on nodes and edges, making it fast and reliable even for large codebases.
- Snapshots capture global statistics, node metadata (including community assignments), and edge signatures in the format
source→target:kind. - The
diff_snapshots()function provides capped results (100 nodes/edges, 50 community changes) to prevent output flooding while preserving summary counts. - All persistence logic in
code_review_graph/graph_diff.pyensures deterministic output by sorting edge lists before JSON serialization.
Frequently Asked Questions
What file format does code-review-graph use for snapshots?
Snapshots are stored as standard JSON files. The format includes sorted lists for edges to ensure deterministic output, making them suitable for version control and CI/CD pipelines where consistent file hashes matter.
How does the diff algorithm handle community detection changes?
For every node present in both snapshots, diff_snapshots() compares community IDs. If a node moved from one community to another, it records the change with the qualified name, previous community ID, and new community ID in the community_changes list (capped at 50 entries).
What are the limits on reported changes in a diff?
The diff_snapshots() function limits detailed reporting to 100 new nodes, 100 removed nodes, 100 new edges, 100 removed edges, and 50 community changes. However, the summary dictionary always reports exact total counts for all categories regardless of these limits.
Can I use graph diffing without the GraphStore database?
Yes. Once you have saved snapshots to JSON files using save_snapshot(), you can load them later with load_snapshot() and compare them using diff_snapshots() without needing the original SQLite database or GraphStore instance available.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →