A good git workflow with AI agents is four habits: start each task from a clean working tree, give each task its own branch, commit whenever the agent reaches a state that works, and read the full diff before you merge. Then everything the agent did is visible, and anything it did can be undone with one command. To run more than one agent at once, give each its own git worktree.
What it looks like in practice
git status
git switch -c agent/fix-session-expiry
You give the agent its task. Ten minutes later it has touched six files.
git diff --stat
git diff
The tests pass and the diff is what you asked for, so you commit it. Or the agent went the wrong way, and you throw everything away:
git switch main
git branch -D agent/fix-session-expiry
Nothing you wrote yourself was at risk, because it was committed or stashed before the agent started.
Why start from a clean working tree?
Because otherwise your own unfinished edits and the agent’s edits end up in the same files, and you can’t review or undo one without the other.
git status
If anything shows as modified, commit it or stash it:
git stash push -u -m "wip before agent task"
-u includes new files you haven’t added yet. Without it, git stash leaves untracked files where they are. Get your work back later with git stash pop.
Should the agent work on its own branch?
Yes. Branches cost nothing and give you:
- A clear review boundary:
git diff main...agent/fix-session-expiryshows only the agent’s work. - Easy abandonment: delete the branch and it never happened.
- A ready pull request if your team reviews on GitHub or GitLab.
A prefix such as agent/ shows at a glance in git branch which work came from an agent.
When should I commit?
Whenever the work reaches a state you would want to come back to: the failing test is written, the fix passes, the cleanup is done. Then a bad later step only costs you that step.
git add -A
git commit -m "Add failing test for session expiry"
Some agents commit on their own, others leave it to you. If yours commits, check what it staged. Local config, build output and .env files should be in .gitignore so they never get there.
When the task is done, squash the checkpoints into one commit:
git switch main
git merge --squash agent/fix-session-expiry
git commit
How do I undo what the agent did?
| You want to | Run |
|---|---|
| Throw away changes to one file | git restore path/to/file |
| Throw away all changes to tracked files | git restore --staged --worktree . |
| Also delete files the agent created | git clean -nd to preview, then git clean -fd |
| Go back to the last commit, all at once | git reset --hard HEAD, then git clean -fd |
| Undo the last commit but keep its changes | git reset --soft HEAD~1 |
| Drop the whole attempt | git switch main then git branch -D agent/... |
Two things catch people out:
- Plain
git restore .skips staged changes. If the agent rangit add, use--staged --worktree. - Neither
git restorenorgit reset --hardremoves new files. That is whatgit cleanis for, and it deletes them for good. Always preview with-nfirst.
Some agents also have their own undo, such as Claude Code’s /rewind and OpenCode’s /undo. It is handy, but git is the undo that works the same across every tool.
How do I run two agents at once?
Give each one its own worktree: a second folder with its own branch, sharing the same repository history. Two agents in one folder will overwrite each other’s edits.
git worktree add -b agent/add-tests ../myapp-add-tests
Point the second agent at ../myapp-add-tests. When you’re done:
git worktree list
git worktree remove ../myapp-add-tests
Removing the worktree keeps the branch, so merge or delete it as usual. git worktree remove refuses if the folder has uncommitted changes, which protects you from losing work.
Some agents can do this for you: claude --worktree feature-auth starts a Claude Code session in a new worktree, and codex --worktree does the same for Codex. The repository needs at least one commit first.
Worktrees separate files, not everything else. Two agents can still collide on the same port, database or Docker container. A second worktree also needs its own dependency install, such as npm install.
Which git commands should need my approval?
These should ask you every time, whatever the agent:
git push, and especiallygit push --forcegit reset --hardandgit clean -fon work you haven’t reviewed- Rewriting shared history:
rebase, orcommit --amendafter a push - Changing remotes or git config
Set this in your agent’s permission rules instead of trusting it to be careful. See AI agent permissions.
How should agent commits be worded?
An agent can draft a good commit message from the diff. Check that it says what changed and why, not what the agent did (“I updated the file to…”). Some teams add a trailer to mark AI-assisted commits:
Fix token expiry unit mismatch
Session expiry compared seconds to milliseconds, so tokens
stayed valid far longer than intended.
Assisted-by: <agent and model>
Whether to mark AI involvement is a team decision. Pick one rule and stick to it.
I threw away the agent’s work by mistake. Can I get it back?
Often, yes, if git ever saw it.
It was committed, then lost through reset --hard, a deleted branch or a bad rebase. Git keeps a log of where HEAD pointed:
git reflog
Find the line from before the accident, for example a41c9e2 HEAD@{3}: commit: Add failing test for session expiry, and bring it back on a new branch:
git branch recovered a41c9e2
It was staged but never committed. git add stores file contents in the repository even without a commit. Ask git for objects nothing points to anymore:
git fsck --lost-found
Git writes them to .git/lost-found/. Staged files land in other/, without their names; open them to find yours.
It was never staged or committed. Then git never had it. Your editor’s local history or a backup is the only chance. This is the real argument for committing checkpoints often: a commit costs nothing, and it makes every later mistake recoverable.
Related guides
- How to review AI-written code: what to look for in the diff
- How to write good tasks for coding agents: one task per branch starts with one clear task
- AI agent permissions: make push and force-push ask first
- Keep secrets away from AI agents: so
.envnever ends up in a commit