· 5 min read ·

Worktrees, Commit Discipline, and the Git Habits That Make Coding Agents Safe to Run

Source: simonwillison

Simon Willison’s guide on agentic engineering patterns covers a topic I’ve been thinking about a lot lately: how to use Git with coding agents in a way that doesn’t leave you dreading what the agent did while you weren’t watching. The short version is that Git stops being just version control and starts being the primary safety mechanism between you and an autonomous process that writes code.

I’ve been running coding agents against my own projects — the Discord bot, a few systems utilities, the blog generator — and the Git habits you develop matter more than almost any other part of the workflow. Let me walk through what works and why.

The Baseline: Commit Before You Start

Before handing off any work to a coding agent, the repository should be in a clean, committed state. This sounds obvious but it’s easy to skip when you’re iterating quickly. If you start an agent session with unstaged changes, you lose the ability to do a clean git diff to see exactly what the agent changed, and you lose a clear rollback point.

The workflow I’ve settled into is:

git add -p   # stage anything I care about
git stash    # or commit, depending on the work
# run the agent
git diff HEAD

That final diff is the review step. It shows exactly what the agent touched. With a clean starting point, this is a legible summary of the session. Without one, it’s noise.

Aider, the CLI coding tool that’s been popular in the open-source community, makes this discipline automatic. By default, Aider commits after every accepted change with an AI-generated commit message describing the edit. The --no-auto-commits flag disables this, but the default behavior is the right call for most workflows. You end up with a granular history of every change the agent made, each commit small enough to review in isolation. If something breaks, git bisect is viable. You can git revert a single bad step without unwinding everything that came after it.

Claude Code takes a different approach — it surfaces proposed commands (including git operations) for approval rather than committing automatically. That’s a reasonable trade-off for an agent that does more varied work, but it means the commit discipline is on you.

Git Worktrees for Parallel Agent Work

The more interesting pattern is using git worktrees to run multiple agents concurrently without them stepping on each other.

A git worktree is an additional working directory attached to the same repository. It checks out a separate branch into a separate directory, but shares the same .git object store. Two worktrees on the same repo can exist simultaneously, each on their own branch, without any of the overhead of a full clone.

git worktree add ../ralph-feature-auth feature/auth-refactor
git worktree add ../ralph-feature-tests feature/add-test-coverage

Now you can point two separate agent sessions at those two directories. They work on independent branches, read and write different files (or the same files without conflicts because the branches don’t merge until you decide to), and produce separate commit histories you can review independently.

The Claude Agent SDK has first-class support for this pattern through the isolation: "worktree" option, which creates a temporary git worktree, runs the agent in it, and cleans up afterward if no changes were made. The worktree and its branch are returned if the agent did make changes, so you can inspect and merge at your own pace.

The isolation this provides isn’t just about avoiding file conflicts. It’s about keeping the blast radius of any one agent session bounded. If an agent on a feature branch does something destructive, main is unaffected. You can delete the worktree and branch without ceremony.

Agents as Context Consumers of Git History

There’s a less obvious use of Git in agent workflows: feeding history into the agent as context. Before asking an agent to fix a bug or extend a feature, you can give it a relevant slice of the commit log:

git log --oneline -20
git show <commit-hash>
git log -p --follow -- src/commands/help.ts

Agents that understand the history of a file make better edits. They can see that a function was refactored two weeks ago for a reason, or that a config key was renamed and the old name is still lurking in a comment. Claude Code’s toolset includes the ability to run these commands directly, so a well-prompted session can pull its own context from the repo’s history.

Aider does something similar when it passes relevant file content into its prompt window, but explicit log context tends to help with anything touching evolving interfaces or recently-changed APIs.

Pre-commit Hooks as a Quality Gate

One pattern that pairs well with agent-heavy workflows is leaning harder on pre-commit hooks. When a human is writing code, hooks are occasionally annoying. When an agent is committing automatically, they’re essential.

A hook that runs the type checker, linter, and a fast test subset before every commit catches the class of agent error that looks syntactically correct but violates project conventions or type constraints. Aider respects pre-commit hooks — if a hook fails, the commit doesn’t happen, and Aider surfaces the error so the agent can try to fix it.

A minimal useful setup for a TypeScript project:

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: tsc
        name: TypeScript check
        entry: npx tsc --noEmit
        language: system
        pass_filenames: false
      - id: eslint
        name: ESLint
        entry: npx eslint --max-warnings 0
        language: system
        types: [ts]

The agent gets immediate feedback on whether its changes are valid, which closes the loop without requiring human review of every intermediate state.

Reviewing Agent Work Before It Merges

The final step is the review itself. Even with clean commits, good messages, and passing hooks, you should read the diff before merging agent work into any shared branch. The discipline here isn’t about distrust — it’s about maintaining the mental model of the codebase that you’d lose if you treated agent-generated code as a black box.

git diff main...feature/agent-work gives you the full picture. For longer sessions, git log --stat main...feature/agent-work gives an overview of which files changed and by how much, which helps triage what needs careful reading versus a quick scan.

The agents I’ve found most useful are the ones that produce small, coherent, well-named commits. A session that results in a single 800-line commit touching fifteen files is harder to review and harder to partially revert than one that produces eight focused commits of 50-100 lines each. Prompt engineering matters here: asking an agent to “make incremental commits as you go” tends to produce better histories than letting it batch everything at the end.

Git isn’t new and none of these patterns are invented for AI. Worktrees have been in git since 2015. Pre-commit hooks are as old as the hills. But the combination of granular commits, worktree isolation, and hook-enforced quality gates adds up to a workflow where coding agents are genuinely useful without becoming a source of opaque, hard-to-audit changes. That’s the discipline worth building.

Was this interesting?