AI Code Review: Capture the Staged Diff Without Missing New Files
TL;DR: Use an explicitly staged patch as the input to AI review of your next commit. Check untracked files before exporting it, and check for later edits before accepting the review. This makes review scope reproducible, but it does not prove that the patch is correct or that your tests ran against it.
What you’ll be able to do after this guide:
- Find the new test file that a plain
git diffleaves out. - Export a staged patch with a base commit and a fingerprint.
- Detect when a review or test result belongs to an older version of your changes.
Honest take: Choose an explicit staged patch for a small change review; an unrestricted repository chat is too easy to confuse with a review of your actual next commit.
An AI reviewer can give a convincing explanation of the wrong code. You ask it to check a bug fix, paste a diff, and receive a clean bill of health. Meanwhile, the test you wrote is still untracked, or the implementation changed after you exported the patch. The problem starts before the model evaluates anything.
This tutorial covers the Git boundary. It does not require a particular assistant subscription, a remote repository, or a model API. The preparation commands run locally. Whatever service you subsequently use for review has its own access rules and charges; nothing here makes that service free or limits what an IDE agent can read.
Understand the three versions before asking for review
For an ordinary repository with an existing commit, think of HEAD as the committed baseline, the index as the staged proposal, and the working tree as the files you are editing. Those can contain three different versions of one file.
Git’s diff documentation distinguishes the comparisons. Plain git diff compares the working tree with the index. git diff --cached compares the index with HEAD; --staged is an alternative spelling. Neither command automatically adds an untracked file to the proposal.
| Input | What it helps review | Main failure to catch |
|---|---|---|
Plain git diff | Edits made after the current staged version | Staged changes and untracked files can be absent |
git diff --cached | The content proposed for the next ordinary commit | New files must be staged first; later working edits are absent |
git diff HEAD | Tracked changes relative to the last commit | Still not a list of all untracked content |
| A committed branch comparison | Changes between selected commits | Your uncommitted work is outside that comparison |
Our recommendation is the second row when your question is “review what I intend to commit.” For a branch-wide review, select and record the appropriate commit range instead. Do not quietly change between these questions halfway through a review session.
What we actually tested
On November 5, 2026, we ran a small repository fixture with Git for Windows 2.53.0.windows.2. The initial committed calc.py implemented addition incorrectly as subtraction. We then changed it to addition and created a new test_calc.py.
Before staging, the plain diff’s filename list contained one file, calc.py. The staged diff was empty. A separate untracked-file query found test_calc.py. After explicitly staging both files, the staged diff contained two files. Its patch occupied 341 bytes in this Windows fixture; that is an artifact size, not a token count or a portable performance measurement.
We then edited the working copy of calc.py again, changing the expression to a + b + 1. The staged blob still contained a + b. The status output was:
MM calc.py
A test_calc.py
This demonstrates a concrete mismatch: a review of the exported staged patch can correctly discuss addition while a test launched in the current working tree executes the later, incorrect expression. We did not run an AI reviewer or measure its defect detection rate. These observations establish which bytes it would receive through this workflow.
Step 1: inventory the repository before staging
Start at the repository root. Close or pause any process that is actively editing the files you intend to review. These commands inspect state without changing it:
git rev-parse --show-toplevel
git status --short
git diff --name-status
git diff --cached --name-status
git ls-files --others --exclude-standard
The last command lists untracked paths while honoring the usual ignore rules, as documented by git-ls-files. An ignored test fixture will not appear there. If a file you expected is missing, investigate its ignore rule separately with git check-ignore -v -- path/to/file; do not force-add every ignored file to compensate.
Read the filenames as a proposed scope. Include the implementation, its tests, and configuration changes that are actually necessary for the fix. Leave unrelated work alone. A generated database dump or local credentials file is not a useful addition just because it is sitting beside the test.
Existing staged work needs particular care. If a colleague or another tool staged something, do not assume you own it. Review the current staged patch before changing the selection. In a shared working directory, agree on the commit boundary or use a separate worktree for your change.
Step 2: stage explicit paths and inspect the result
For our example, the intended selection is simple:
git add -- calc.py test_calc.py
git diff --cached --name-status
git diff --cached --stat
git diff --cached --check
git diff --cached -- calc.py test_calc.py
Git add stages the content at the time you invoke it. It does not establish a live connection that automatically stages subsequent edits. Use git add -p -- calc.py when only part of a tracked file belongs to the change, then read the staged output carefully.
The --check command can identify certain whitespace problems; passing it is not a code correctness test. The filename list is your first check for the missing new test. The actual diff is your check that the test asserts the behavior you intend and that unrelated hunks have not slipped in.
If you staged the wrong file in a repository with an existing HEAD, git restore --staged -- path/to/file changes the index selection while leaving that file’s working contents in place. Verify the result with status. Do not add --worktree to that command unless you separately intend to replace working files. See the precise options in git-restore.
Step 3: export a packet without shell encoding surprises
Use a fresh output directory outside the repository so the exported files do not become new untracked project files. Save this original helper as export_review.py outside the project, then run it from the repository root with Python 3. It needs an existing HEAD and a nonempty staged diff.
import hashlib
import json
from pathlib import Path
import subprocess
import sys
def git(*args):
return subprocess.check_output(["git", *args])
out = Path(sys.argv[1]).resolve()
repo = Path(git("rev-parse", "--show-toplevel").decode().strip()).resolve()
if out == repo or repo in out.parents:
raise SystemExit("Choose an output directory outside this repository")
base = git("rev-parse", "HEAD").decode().strip()
patch = git("diff", "--cached", "--no-ext-diff", "--no-textconv",
"--no-color", "--binary", "--full-index", "--unified=3")
if not patch:
raise SystemExit("No staged changes to review")
out.mkdir(parents=True, exist_ok=False)
(out / "review.patch").write_bytes(patch)
manifest = {
"base_commit": base,
"patch_sha256": hashlib.sha256(patch).hexdigest(),
"patch_bytes": len(patch),
"status": git("status", "--short").decode("utf-8", errors="replace"),
}
(out / "manifest.json").write_text(
json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
print(json.dumps(manifest, indent=2))
For example, if your repository is projects/demo, choose a sibling directory such as projects/review-packet-01. Pass its path as the script’s sole argument. The script deliberately refuses to overwrite an existing packet. Byte output avoids relying on a shell’s text-redirection encoding.
The helper exports the entire staged diff. That is intentional: first make the index match the intended commit. If you instead export selected paths, record that narrower scope and say plainly that other staged paths were excluded. Binary patch data preserves an artifact but is not a useful visual review of an image, executable, or archive; inspect such files with an appropriate separate tool.
The fingerprint identifies the exported bytes. It is not an approval signature, a security assessment, or evidence that your next commit will contain identical content. Pause writers while capturing the packet: these sequential Git calls are not an atomic snapshot of concurrent activity.
Step 4: give the reviewer a bounded task
Attach the patch and manifest through your approved review channel. A useful instruction is:
Review this staged patch against the recorded base commit.
Look for behavior regressions and missing tests in the changed code.
For each finding, name the changed path, relevant hunk, failure case,
and a concrete test that could confirm it.
If a finding needs surrounding code that is not provided, request it.
Do not claim that tests passed or that unrelated files were reviewed.
Do not edit files during this review.
A text instruction defines the task, not the assistant’s technical permissions. An IDE assistant may also have repository access or automatically supplied context. Check its actual configuration if the boundary matters. For background on tool execution boundaries, our Cline review and Aider review cover different editing workflows; this packet can serve as an independent record regardless of your editor.
Provide surrounding code when a finding needs it. A three-line hunk cannot establish every caller’s contract. Keep additional context labeled separately so someone reading the review can distinguish changed lines from explanatory files. If the reviewer invents a function or cites a path absent from the packet, ask it to locate the supporting evidence before acting on the claim.
Step 5: tie fixes and tests to the same version
After a review finding, make the fix and run the relevant tests. Then explicitly stage the revised implementation and tests and create a new packet in a new directory. A materially changed patch needs another review; the earlier favorable response does not transfer automatically.
Before committing, inspect both sides again:
git status --short
git diff --cached --check
git diff --cached
git diff
Read MM correctly: the first column describes the index relative to the committed version, and the second describes working changes relative to the index. Git documents that format in git-status. In our fixture, the second M was the reason an ordinary working-tree test would not validate the staged implementation.
For a small change, align the relevant working files and staged contents deliberately before the final test run. If unrelated edits prevent that, test the proposed change in an isolated checkout under your normal project workflow. Do not describe a working-tree test as a test of a staged-only version you never executed. Record the command, result, and version tested alongside the patch fingerprint.
Honest take: make the patch boundary boring
The staged workflow wins for a focused next-commit review because you can inspect and reproduce its input. Its weakness is that humans still choose the scope, and an assistant still needs enough surrounding context to reason correctly. Neither a neat manifest nor a clean AI response replaces tests and human judgment.
Use the three checks every time: find untracked files, read the staged proposal, and check for edits made after export. They address distinct failure modes. Adding a more expensive reviewer before fixing those boundaries only gives you a more expensive review of potentially incomplete evidence.
Sources and verification
- Git diff: comparison modes and patch export options.
- Git add: staging contents and interactive selection.
- Git status: short-format index and working-tree columns.
- Git ls-files: untracked files and standard exclusions.
- Git restore: index-only restoration.
- Local repository fixture: Git for Windows 2.53.0.windows.2; one modified tracked file, one untracked test, explicit staging, then a later working-tree edit. No model-quality benchmark was performed.
Last updated November 5, 2026. Official Git documentation checked and the local Git fixture executed on this date.
Was this article helpful?
Thanks for the feedback — it helps improve future articles.
Need hands-on help?
I offer 1-on-1 technical consulting for local AI setup, GPU selection, and AI coding tool configuration — same topics covered on this site.
Book a session — $49 / hour →Know which coding tool is worth paying for
Hands-on comparisons of AI coding assistants and what each one costs to run — including the local-model path. Sent only when something changes. Unsubscribe anytime.