How Graph Diffs Reveal Git History Co‑Change Relationships in Code Review Graph
Graph diffs provide the structural, language‑level representation of Git co‑change events by capturing exactly which symbols, edges, and community memberships change between commits.
The code‑review‑graph project by tirth8205 builds a full‑text, language‑aware code graph that turns Git history into queryable structural data. Understanding the relationship between graph diffs and Git history co‑change unlocks precise, program‑level insight into how code evolves together over time.
What Graph Diffs Capture
In code_review_graph/graph_diff.py, the take_snapshot() function records the complete state of the code graph at any commit. A snapshot includes node counts, edge sets, and community assignments for all symbols in the repository.
The diff_snapshots() function then compares two snapshots to produce a structured report of changes:
- New nodes – symbols (functions, classes, files) added between commits
- Removed nodes – symbols deleted
- New edges – call relationships, imports, or file‑level dependencies introduced
- Removed edges – relationships broken
- Community changes – symbols that moved between logical groups
from code_review_graph.graph_diff import take_snapshot, diff_snapshots
# Capture state at commit A
before = take_snapshot(store) # graph_diff.py:L15‑L23
# Capture state at commit B
after = take_snapshot(store)
# Compute structural changes
diff = diff_snapshots(before, after) # graph_diff.py:L64‑L78
How Git History Co‑Change Is Defined
The evaluation benchmark in code_review_graph/eval/benchmarks/impact_accuracy.py defines co‑change as a specific measurement mode:
MODE_CO_CHANGE = "co-change (same commit, seed excluded)" # impact_accuracy.py:L30
This mode builds ground‑truth by examining Git logs: two symbols co‑change if they appear in the same commit (excluding the seed file that triggered analysis). The benchmark then validates whether the graph correctly predicts these relationships.
The Direct Relationship: Graph Diffs as Structural Co‑Change
Git co‑change events manifest as specific patterns in graph diffs. When a commit modifies multiple files, the resulting diff exposes the concrete structural impact:
| Git event | Graph diff manifestation |
|---|---|
| Two files touched in same commit | New edges linking nodes across file boundaries |
| Function added and called | New node + new edge in single diff |
| Refactoring moves logic between modules | Community changes + edge rewire |
The benchmark treats these diff patterns as predicted co‑change signals. Where Git history says "these files changed together," the graph diff explains how: which specific symbols gained dependencies, which communities restructured, and which new call paths formed.
Practical Workflow for Extracting Co‑Change Data
Follow this pattern to surface co‑change relationships using the library:
from pathlib import Path
from code_review_graph.graph import GraphStore
from code_review_graph.graph_diff import take_snapshot, diff_snapshots
# Initialize indexed repository
store = GraphStore(root=Path("/path/to/repo"))
# 1. Snapshot before target commit
snap_before = take_snapshot(store)
# ... apply Git commit or checkout ...
# 2. Snapshot after commit
snap_after = take_snapshot(store)
# 3. Compute structural diff
diff = diff_snapshots(snap_before, snap_after)
# 4. Extract co‑change indicators
new_nodes = diff["new_nodes"] # New symbols introduced
new_edges = diff["new_edges"] # New dependencies formed
community_moves = diff["community_changes"] # Logical group migrations
print("New symbols:", [n["qualified_name"] for n in new_nodes])
print("New dependencies:", new_edges)
print("Community moves:", community_moves)
Each element in new_edges represents a concrete co‑change: two symbols now connected that were not before, captured because they appeared in the same commit.
Why Graph Diffs Surpass File‑Level Co‑Change
Precision at symbol level. Simple file‑level co‑change flags that two files changed together but misses which functions now interact. The diff_snapshots output in graph_diff.py exposes exact qualified names and edge types.
Community dynamics captured. When diff_snapshots reports community_changes (lines 84‑99), it records symbols that shifted logical groups. This structural refactoring signal is invisible to raw Git logs.
Dependency directionality. New edges carry semantic meaning—imports, calls, containment—that raw co‑change counts cannot express.
Key Source Files and Their Roles
| File | Purpose | Co‑change relevance |
|---|---|---|
code_review_graph/graph_diff.py |
take_snapshot() and diff_snapshots() implementation |
Produces the structural diff that predicts co‑change |
code_review_graph/eval/benchmarks/impact_accuracy.py |
Defines MODE_CO_CHANGE and ground‑truth construction |
Validates that graph diffs correctly identify Git co‑change |
code_review_graph/graph.py |
GraphStore with get_stats() and community IDs |
Provides node/edge data used in snapshots |
tests/test_eval.py |
Test suite for evaluation modes | Confirms co‑change handling behavior |
Summary
- Graph diffs are the structural realization of Git co‑change events—what Git tracks at file level, the code graph exposes at symbol and edge level
- The
diff_snapshotsfunction incode_review_graph/graph_diff.pygenerates predictions that theimpact_accuracybenchmark validates against Git history - New edges in diffs directly correspond to co‑changing symbols introduced in the same commit
- Community changes (line 84‑99) capture refactoring co‑change invisible to file‑level analysis
Frequently Asked Questions
How does diff_snapshots identify which symbols changed together?
diff_snapshots compares node and edge sets between two snapshots taken via take_snapshot. Any edge connecting nodes from different files that appears in the diff indicates those symbols were introduced or modified in the same commit—this is the structural definition of co‑change used by the benchmark.
Can graph diffs detect co‑change without rebuilding the entire graph?
No. The current implementation requires full snapshots before and after because take_snapshot() calls store.get_stats() to capture complete node, edge, and community state. Incremental diffing would require tracking per‑commit delta events during indexing.
What is the difference between MODE_CO_CHANGE and other impact accuracy modes?
MODE_CO_CHANGE specifically tests whether symbols appearing in the same Git commit (excluding the seed) are connected in the graph. Other modes in impact_accuracy.py test different structural predictions such as direct callers or community neighbors without the Git‑history constraint.
When would community changes indicate co‑change versus independent refactoring?
A community change in diff_snapshots signals co‑change when it occurs alongside new edges linking the moved symbol to other modified symbols. Isolated community migration without edge changes suggests refactoring that did not co‑evolve with other logic—still valuable, but a different evolution pattern.
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 →