How to Compare Graph Snapshots Using Graph Diff in Code Review Graph

To compare graph snapshots, use the graph_diff module to capture the current state with take_snapshot(), persist it with save_snapshot(), then load two snapshots and run diff_snapshots() to detect added or removed nodes, edges, and community migrations.

The tirth8205/code-review-graph repository provides a SQLite-backed GraphStore that represents your entire codebase as a knowledge graph. Comparing graph snapshots using graph diff enables you to track exactly how symbols and their relationships evolve between any two points in time, such as before and after a major refactoring.

Capturing a Graph Snapshot

The take_snapshot() function in code_review_graph/graph_diff.py walks the GraphStore and returns a lightweight dictionary that freeze-frames the graph state. This snapshot records:

  • Total node and edge counts via GraphStore.get_stats()
  • Every node's qualified name, kind, source file, and community assignment via get_all_nodes() and get_all_community_ids()
  • A complete set of edges (source → target : kind) via get_all_edges()
from code_review_graph.graph_diff import take_snapshot

snapshot = take_snapshot(my_store)  # my_store is a GraphStore instance

Because the snapshot is built entirely through the public GraphStore API defined in code_review_graph/graph.py, it captures the exact database state without requiring direct SQLite access.

Persisting Snapshots to Disk

Use save_snapshot() to write the snapshot dictionary to a JSON file. The function converts the internal edge set to a sorted list to guarantee stable, deterministic output.

from pathlib import Path
from code_review_graph.graph_diff import save_snapshot

save_snapshot(snapshot, Path("before.json"))

This serialization step is essential for comparing graph snapshots across different process executions or after codebase updates.

Loading and Comparing Snapshots

To perform the comparison, first restore your saved states using load_snapshot(), which reads the JSON file and converts the edge list back into a Python set for efficient set operations.

from code_review_graph.graph_diff import load_snapshot

before = load_snapshot(Path("before.json"))
after = load_snapshot(Path("after.json"))

Next, invoke diff_snapshots(before, after) to compute the delta. This function performs set differences on node keys and edge keys, then walks the intersection to detect community ID changes.

from code_review_graph.graph_diff import diff_snapshots

changes = diff_snapshots(before, after)
print(changes["summary"])

Interpreting the Diff Results

The dictionary returned by diff_snapshots() contains five key sections:

  • new_nodes and removed_nodes – Qualified names and full metadata for symbols that were added or deleted.
  • new_edges and removed_edges – Edge signatures (source, target, kind) representing created or dropped relationships.
  • community_changes – Nodes that remained in the graph but were reassigned to a different community ID.
  • summary – Compact counts of total additions, deletions, and migrations.

Because the underlying data structures are plain Python collections, the diff operation is fast, deterministic, and requires no database connectivity.

End-to-End Example

The following workflow demonstrates how to compare graph snapshots using graph diff after updating your codebase:

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,
)

# Initialize the store (e.g., from a temporary DB)

store = GraphStore("tmp_graph.db")

# Populate the store via parsing and indexing...

# Capture the "before" state

before = take_snapshot(store)
save_snapshot(before, Path("snap_before.json"))

# ... make code changes, re-run the indexer ...

# Capture the "after" state

after = take_snapshot(store)
save_snapshot(after, Path("snap_after.json"))

# Load and diff

before = load_snapshot(Path("snap_before.json"))
after = load_snapshot(Path("snap_after.json"))
diff = diff_snapshots(before, after)

print("=== Summary ===")
print(diff["summary"])
print("\nNew nodes (first 5):")
print(diff["new_nodes"][:5])
print("\nRemoved edges (first 5):")
print(diff["removed_edges"][:5])

Unit tests validating this behavior are located in tests/test_tools.py and tests/test_graph.py, which verify both the diff logic and the underlying node/edge storage integrity.

Summary

  • take_snapshot() captures the complete GraphStore state—including node metadata, edges, and community assignments—through the public API in graph.py.
  • save_snapshot() and load_snapshot() handle JSON serialization and deserialization, ensuring edge sets are stored as sorted lists for stability but restored as sets for efficient computation.
  • diff_snapshots() executes set operations to identify added or removed nodes and edges, plus tracks community reassignments via intersection analysis.
  • All operations read from the SQLite schema indirectly through GraphStore methods, eliminating the need for raw database queries.

Frequently Asked Questions

Where is the graph diff utility implemented?

The implementation resides in code_review_graph/graph_diff.py, which imports and utilizes the GraphStore class defined in code_review_graph/graph.py.

What format does the snapshot use for storage?

Snapshots are persisted as JSON files. Edge data is converted to a sorted list during serialization to ensure deterministic output, then transformed back into a Python set when loaded to optimize diff performance.

Can the diff detect when a node changes communities without being deleted?

Yes. The community_changes key in the diff result contains entries for nodes that remained in the graph but were assigned to a different community ID, allowing you to track modular restructuring.

Is the snapshot process dependent on specific database transactions?

No. The snapshot reads from the live GraphStore using methods like get_all_nodes() and get_all_edges(), capturing the state at the exact moment of the call regardless of ongoing transactions.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →