Simon Willison’s guide on using Git with coding agents captures something that took me a while to internalize: the relationship between you and Git changes when an AI is writing most of the code. The mental model you built up over years of solo or collaborative development doesn’t quite map onto what agentic sessions actually require.
When you write code yourself, Git is primarily a history tool. You commit when you reach a meaningful checkpoint, and the log becomes a record of deliberate decisions. When an agent writes code, that model breaks down. The agent might make fifty file changes in three minutes. Some of them will be correct; some will be subtly wrong in ways you won’t notice until later. The commit history you build during an agent session is no longer just a record, it’s the mechanism that lets you recover.
Commit Before You Start, Every Time
The single most useful habit I’ve developed is committing everything before handing control to an agent. Not stashing, not ignoring dirty state, actually committing. The reason is simple: git diff HEAD becomes your primary review tool once the agent finishes, and that diff is only useful if HEAD represents a clean known state.
This is the “commit everything” pattern that Willison describes. When you start from a clean tree, the diff at the end of a session tells you exactly and completely what the agent changed. When you start from a dirty tree, the diff is noise mixed with signal and separating them is tedious.
Aider, which has been doing agent-assisted development longer than most tools, defaults to auto-committing after every LLM response that produces file changes. This isn’t accidental. Each commit corresponds to one agent turn, so git log becomes a literal transcript of the session with attached diffs. You can run git show HEAD~3 to see exactly what the agent changed two turns ago, before it went off in the wrong direction.
# Aider's auto-commit behavior creates a per-turn history
git log --oneline
# a3f9d2e aider: Refactor auth middleware to use new token format
# b7c1a11 aider: Add token expiry validation to login handler
# 9d4e821 aider: Update User model to include refresh_token field
This granularity matters more than it seems. When an agent produces a long chain of changes and somewhere in the middle it introduced a bug, you want to bisect the agent’s own work, not just your own commits mixed with the agent’s output as one undifferentiated blob.
Worktrees as Isolation Boundaries
Git worktrees are one of those features that most developers never reach for because they solve a problem that solo development rarely surfaces. The git worktree command lets you check out multiple branches of the same repository into separate directories simultaneously, all sharing the same object store.
# Create an isolated working tree on a new branch
git worktree add /tmp/agent-session-1 -b feature/auth-rewrite
# Run your agent inside that directory
cd /tmp/agent-session-1
claude # or aider, or whatever agent tooling you use
# Review what happened
git diff main
# Clean up if it went wrong
git worktree remove /tmp/agent-session-1
git branch -d feature/auth-rewrite
For agent workflows, worktrees solve two distinct problems. The first is contamination: if the agent modifies your main working directory and something goes wrong partway through, you’re in a messy state. A worktree failure is just a directory deletion. The second is parallelism: you can run multiple agents on different tasks simultaneously in different worktrees without them interfering with each other’s branches or staged changes.
Claude Code supports this pattern explicitly. Running it inside a worktree means the agent operates on an isolated branch and cannot accidentally touch files in your main checkout. The .git directory is shared, so the agent has full git context and history, but the working tree and index are separate.
The storage overhead is minimal. Git worktrees share the object database, so you’re not duplicating repository history. The worktree itself only adds the actual working files and a small metadata directory under .git/worktrees/.
The Diff as the Review Interface
When you write code yourself, code review happens at PR time and reviewers look at the diff. When an agent writes code, the diff review step needs to happen before you commit or merge, and it needs to happen every session, not just when you open a PR.
# See everything the agent changed in this session
git diff HEAD
# Get a statistical overview first
git diff --stat HEAD
# Review file by file
git diff HEAD -- src/auth/middleware.ts
This is where the commit-before-starting habit pays off. The diff between your clean HEAD and the current working tree is the complete ledger of what the agent did. No more, no less.
One pattern worth building into your workflow: before accepting any agent session, check the diff for files that shouldn’t have changed. Agents occasionally make “helpful” modifications to adjacent files that weren’t part of the task. A dependency file update you didn’t ask for, a config change that seemed logical to the model, a test file modified to make a failing assertion pass. The diff will catch all of this if you look.
For longer sessions, breaking the review into chunks by looking at individual commits (when using Aider’s auto-commit mode or similar) makes the review more manageable than staring at five hundred changed lines at once.
Branch Per Task, Without Exception
The worktree pattern implies this, but it’s worth stating directly: every agent task should live on its own branch. Not because of any CI/CD convention, but because it gives you a stable rollback point and a clean merge decision.
The branch-per-task discipline also makes the git log more honest. When you look at your repository history six months later, you want to be able to tell which commits came from agent sessions and which came from your own hands. Keeping agent work on feature branches with clear names preserves that signal.
GitHub Copilot Workspace takes this to its logical conclusion by treating the entire workflow as PR-first: the agent always works on a branch, and the output is always a pull request to be reviewed before merging. This is more friction for small tasks but makes the review step structural rather than optional.
What Skipping These Patterns Costs You
The failure mode is consistent: you run an agent session without committing first, accept the changes without reviewing the diff, and discover two days later that something is broken. Bisecting the problem now requires reasoning about what the agent did based on current state, without a clean before-after snapshot.
This isn’t hypothetical. The messiest debugging sessions I’ve had in the past year involved agent-generated code where I didn’t have a clean commit to diff against. The cleanest sessions had a commit per agent turn and a branch per task.
The Git documentation on worktrees is worth reading if you haven’t used them before. The feature has been stable since Git 2.5 (released 2015) and the workflow for agent use is genuinely different from how most people think about it.
The discipline required isn’t complicated: clean state before you start, a branch for the work, frequent commits during, a diff review before you accept. The tools mostly support this; Aider does it automatically, Claude Code and others support it with minimal setup. The gap is usually habit, not tooling.