# How diff-match-patch Generates Code Change Previews in code-graph-rag

> Learn how diff-match-patch generates code change previews in code-graph-rag. Discover the semantic difference computation and unified diff rendering process.

- Repository: [Vitali Avagyan/code-graph-rag](https://github.com/vitali87/code-graph-rag)
- Tags: how-to-guide
- Published: 2026-08-16

---

**Short answer:** The `FileEditor` class uses Google's diff-match-patch library to compute semantic differences between original and modified function code, then renders a unified diff preview using Python's `difflib`.

The `code-graph-rag` repository implements a surgical code-editing system that lets LLMs propose precise changes to specific functions. Understanding how it generates readable change previews requires examining the `FileEditor` class in [`codebase_rag/tools/file_editor.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/tools/file_editor.py), where diff-match-patch performs the heavy lifting of comparing code versions.

## The Core diff-match-patch Workflow

The preview generation follows a four-step pipeline that balances algorithmic precision with human readability.

### Step 1: Extract Original Function Source

`FileEditor.get_function_source_code()` uses Tree-sitter parsers to locate and extract the exact source text of the target function:

```python
original_code = self.get_function_source_code(
    file_path, function_name, line_number
)

```

This ensures the diff operates on *semantic units* (complete functions) rather than arbitrary line ranges.

### Step 2: Generate Raw Diff

The `diff_match_patch.diff_main()` method produces a low-level edit script:

```python
diffs = self.dmp.diff_main(original_code, new_code)

```

This returns a list of tuples: `(operation, text)` where operation is `-1` (delete), `0` (equal), or `1` (insert).

### Step 3: Semantic Cleanup

Raw diffs often contain noisy, minimal edits. The `diff_cleanupSemantic()` method merges adjacent operations and eliminates trivial differences:

```python
self.dmp.diff_cleanupSemantic(diffs)

```

This step is crucial for code—grouping related changes so `x = 1` becoming `x = 2` appears as a single replacement rather than delete-then-insert.

### Step 4: Render Unified Diff Preview

Finally, `difflib.unified_diff` formats the result as the standard `@@ -a,b +c,d @@` format developers recognize:

```python
diff = difflib.unified_diff(
    original_code.splitlines(keepends=True),
    new_code.splitlines(keepends=True),
    fromfile=f"original/{function_name}",
    tofile=f"new/{function_name}",
)
return "".join(diff)

```

## Complete Implementation in FileEditor.get_diff

The full method in [`codebase_rag/tools/file_editor.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/tools/file_editor.py) (lines 63-86) orchestrates this pipeline:

```python
def get_diff(
    self,
    file_path: str,
    function_name: str,
    new_code: str,
    line_number: int | None = None,
) -> str | None:
    original_code = self.get_function_source_code(
        file_path, function_name, line_number
    )
    if not original_code:
        return None

    diffs = self.dmp.diff_main(original_code, new_code)
    self.dmp.diff_cleanupSemantic(diffs)

    diff = difflib.unified_diff(
        original_code.splitlines(keepends=True),
        new_code.splitlines(keepends=True),
        fromfile=f"original/{function_name}",
        tofile=f"new/{function_name}",
    )
    return "".join(diff)

```

## Why diff-match-patch and difflib Together?

The dual-library approach serves complementary purposes:

- **diff-match-patch** – Provides **semantic diff cleanup** optimized for natural language and code, reducing false positives from formatting changes
- **difflib.unified_diff** – Generates the **industry-standard unified format** that appears in Git, code review tools, and developer workflows

This combination ensures the preview is both *algorithmically sound* and *immediately comprehensible* to users.

## From Preview to Applied Patch

When users approve a preview, the same `diff_match_patch` instance creates and applies the actual patch. The `replace_code_block` method (lines 41-53) handles this:

```python
patches = self.dmp.patch_make(original_content, modified_content)
patched_content, results = self.dmp.patch_apply(patches, original_content)

```

The `patch_apply` method returns both the modified content and a list of boolean results indicating which hunks succeeded—enabling precise error reporting if a patch fails partially.

## Practical Example: Generating a Preview

```python
from codebase_rag.tools.file_editor import FileEditor

# Initialize editor with project root

editor = FileEditor(project_root="/path/to/project")

# Proposed function replacement

new_code = """
def calculate_total(items):
    return sum(item.price for item in items)  # Modernized

"""

# Generate preview diff

preview = editor.get_diff(
    file_path="cart/utils.py",
    function_name="calculate_total",
    new_code=new_code,
)

print(preview)

```

**Sample output:**

```diff
--- original/calculate_total
+++ new/calculate_total
@@ -1,5 +1,3 @@
 def calculate_total(items):
-    total = 0
-    for item in items:
-        total += item.price
-    return total
+    return sum(item.price for item in items)  # Modernized

```

This preview appears in the LLM interface for user approval before `apply_patch_to_file` executes the change.

## Key Source Files

| File | Role |
|------|------|
| [`codebase_rag/tools/file_editor.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/tools/file_editor.py) | Contains `FileEditor` class with `get_diff()`, `replace_code_block()`, and `apply_patch_to_file()` |
| [`codebase_rag/constants/__init__.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/__init__.py) | Defines status message templates like `MSG_SURGICAL_SUCCESS` |
| [`codebase_rag/parser_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/parser_loader.py) | Loads Tree-sitter parsers for function extraction |
| [`codebase_rag/tool_descriptions.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/tool_descriptions.py) | Exposes `REPLACE_CODE` tool to the LLM |

## Summary

- **diff-match-patch** generates semantically meaningful diffs through `diff_main()` followed by `diff_cleanupSemantic()`
- **difflib.unified_diff** renders the final preview in the standard unified format
- The `FileEditor` class in [`codebase_rag/tools/file_editor.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/tools/file_editor.py) coordinates extraction, comparison, cleanup, and formatting
- Identical diff-match-patch primitives create and apply patches after user approval
- Tree-sitter integration ensures diffs operate on complete, syntactically valid functions

## Frequently Asked Questions

### Can diff-match-patch handle large files efficiently?

According to the code-graph-rag implementation, **diff-match-patch operates on function-level chunks** rather than entire files. The `get_function_source_code()` method extracts only the relevant function body, keeping inputs small. For typical function sizes, the O(ND) Myers algorithm in diff-match-patch performs acceptably.

### What happens if the original function changes after preview generation?

The `patch_apply` method in `apply_patch_to_file` includes **fuzzy matching** that tolerates minor context shifts. If the patch fails, `results` contains `False` for failed hunks, and the system reports partial failures via `MSG_SURGICAL_SUCCESS` or similar status constants.

### Why use semantic cleanup instead of raw diffs?

Raw diffs from `diff_main()` produce minimal edit sequences that often split logically related changes. `diff_cleanupSemantic()` merges adjacent operations and respects **word boundaries and code structure**, yielding previews that align with developer mental models.

### Is the unified diff output compatible with `git apply`?

The output format matches standard unified diff, but **paths are synthetic** (`original/{function_name}` rather than real filesystem paths). For Git compatibility, transform the header or use `patch_apply` directly through code-graph-rag's API instead of external Git tooling.