Review an agent's branch before the pull request: a checklist with the git commands
Read scope, tests, dependencies and config before the code itself. Each step is a git command run against the point where the branch started.
An agent's branch arrives finished and confident, and often larger than the task. Reading it top to bottom in file order is the slowest way to find what matters. Check the parts that are cheap to check and expensive to miss first: what changed, whether the tests still test anything, what was added to dependencies and config. Then read the code.
Every command below runs inside the agent's worktree, with main as the base. Swap in your own base branch.
1. Diff against where the branch started
Use three dots: git diff main...HEAD. Git's documentation defines it as the diff from the merge base of the two branches to HEAD, which is exactly the agent's work. Two dots compare the tips, so anything merged to main since the agent started shows up reversed, as if the agent had deleted it. In a small test repository, one commit to main after the branch started:
$ git diff --stat main..HEAD
README.md | 1 -
src/math.js | 1 +
src/math.test.js | 3 +++
$ git diff --stat main...HEAD
src/math.js | 1 +
src/math.test.js | 3 +++The agent never touched README.md. Only the three-dot diff says so.
2. Check the scope before the content
git log --oneline main..HEAD
git diff --stat main...HEAD
git diff --name-only --diff-filter=A main...HEAD # added files
git diff --name-only --diff-filter=D main...HEAD # deleted filesAsk of every file: does this belong to the task? Agents often tidy neighbouring code, rename things on the way past and add helpers nobody asked for. Google's review guide asks reviewers to be "especially vigilant about over-engineering", and that advice fits agent output well. Deleted files deserve a look every time. If the scope is wrong, send it back now, before you spend time reading code that should not be there.
3. Make sure the tests still test something
A test suite can pass because the code works or because the tests were loosened. Look for the second case directly. -G limits the diff to changes whose added or removed lines match a pattern:
# Tests skipped, focused or marked as expected failures
git diff -G'\.(skip|only)\(|@pytest\.mark\.(skip|xfail)|#\[ignore\]' main...HEAD
# Every change to test files, read on its own
git diff main...HEAD -- '*test*' '*spec*'Then check that the new tests fail without the change. Do it in a throwaway worktree, so nothing in your own checkout is touched. Check out the merge base there, copy the branch's test files over it, and run them:
base=$(git merge-base main HEAD)
head=$(git rev-parse HEAD)
git worktree add --detach ../old-code "$base"
cd ../old-code
git diff --name-only --diff-filter=AM "$base" "$head" -- ':(glob)**/*.test.*' ':(glob)**/*.spec.*' |
git restore --source="$head" --pathspec-from-file=-
npm ci && npm test # the new tests should fail here
cd - && git worktree remove --force ../old-codeThe worktree holds the old source with the branch's tests, and your own checkout, with any uncommitted edits, stays as it was. The diff lists only the test files the branch added or changed, so a pattern that matches nothing is harmless; adjust the two patterns to your project's naming. If the new tests pass against the old code, they do not test the change. Google's guide puts the question plainly: "Will the tests actually fail when the code is broken?"
4. Dependencies and lockfiles
git diff main...HEAD -- package.json pyproject.toml go.mod Cargo.toml
git diff --stat main...HEAD -- '*lock*' 'go.sum'For each new dependency: is it the package you think it is, spelled the way its maintainers spell it, maintained, and needed at all? A large lockfile change from a small manifest change usually means the agent upgraded more than it added. That can be fine, but it should be a decision, not a side effect.
5. Config, CI and suppressed warnings
git diff --stat main...HEAD -- .github/ Dockerfile '*.yml' '*.yaml' '*.toml' '.env*'
git diff -G'eslint-disable|@ts-ignore|@ts-expect-error|noqa|type: ignore|nolint' main...HEADWhen a type check or a linter stands between an agent and a green run, a suppression comment is the shortest way through. Each one needs a reason you agree with. Changes to CI workflows and container files change what runs with your credentials, so read them line by line.
6. Secrets
An agent can copy a value from a .env file or from terminal output into code or a test fixture. Scan the branch's commits before they leave your machine. With Gitleaks installed:
gitleaks git --log-opts="main..HEAD"If a real key was committed, rotate it. Rewriting the branch does not help once the commit has been pushed anywhere.
7. Now read the code
With scope, tests, dependencies and config settled, the code review proper is smaller. Google's list is a good order: design, functionality, complexity, tests, naming, comments. Two questions matter more than usual for agent code:
- Does it fit the codebase? Agents can write a second version of something the project already has. Search for the domain words in the diff and see whether an existing module already does the job.
- Do the comments explain why? The guide says comments should explain why code exists, not what it does. Comments that narrate the change ("now we call the new helper") add nothing; delete them.
8. After you ask for changes
Record the tip before the agent revises, so you only re-read what changed:
old=$(git rev-parse HEAD)
# ... the agent revises ...
git diff "$old" HEAD # if it added commits
git range-diff main "$old" HEAD # if it amended or rebasedgit range-diff pairs each old commit with its new version and shows the difference between the two patches. It pairs commits whose patches are similar enough; a commit that was rewritten heavily shows up as one removed and one added commit.
The checklist
- Diff with three dots:
main...HEAD. - Scope: every file belongs to the task; deletions are intended.
- Tests: nothing skipped or loosened; new tests fail on the old code.
- Dependencies: each one named correctly, maintained and needed.
- Config and CI: read line by line; every suppression has a reason.
- Secrets: scanned before the push.
- Code: design, fit with the codebase, then the details.
- Rework: review only the difference from the last tip.
Tenslo Code puts the first step in the app: a branch review that shows every change against the base in one diff, with staging, commits and the pull request in the same place.
Sources
- git-diff documentation, Git
- git-restore documentation, Git
- git-range-diff documentation, Git
- What to look for in a code review, Google engineering practices
- Gitleaks, Gitleaks on GitHub