Founder pricing: Pro at $9.99/mo forever for the first 50 members. 18 of 50 left Claim yours →
All posts

AI agent commits: keep a git history you can actually revert

The SanuDesk team 6 min read
git workflow ai agents

23:47. Checkout is throwing 500s for about one user in twenty, and you already know which afternoon did it. You open the log:

a3f1c9e  Implement user profile improvements

One commit. Thirty-one files. Inside it: the profile work you asked for, a currency helper the agent tidied on the way past, a dependency bump it decided was related, and the one change you actually need to undo.

git revert a3f1c9e takes out the whole afternoon, working parts included. git bisect has nothing to bisect: your last three commits are three afternoons. So you do it the slow way, reading thirty-one files at midnight, hunting for the line that matters.

The code was fine. The history was also a deliverable, and nobody wrote it.

Why AI coding agents produce one giant commit

An agent commits when the conversation ends, not when a change becomes independently revertable. Its unit of work is your prompt. Yours is the thing you might one day take back out. Those two rarely line up, and the longer the session runs, the further apart they drift.

The message has the same problem. It gets written from the plan, not from the diff, so it inherits the optimism of the prompt instead of reporting what landed. Researchers who read 23,247 agent-authored pull requests found the most common inconsistency was descriptions claiming changes that were never implemented. Only 1.7% of the pull requests scored high on that, but those were accepted 28.3% of the time against 80.0% for the rest, and took 3.5 times longer to merge. A description of work that does not exist is worse than no description, because you trust it once.

One commit per thing you might undo

The rule that fixes most of this is short: a commit is a unit of revert, not a unit of work.

Apply it with one question. If this turns out to be wrong at midnight, is there exactly one commit to remove, and does the tree still work after it is gone? If not, the change wants splitting.

That is a policy an agent can follow, once you write it into the brief or your agent instructions file instead of hoping for it:

Commit each self-contained change as you finish it, before starting the next one. Never mix a refactor with a behavior change. Never bundle formatting or import sweeps into a feature commit. If the task makes you touch a file outside its scope, stop and tell me.

Notice this is the same question as how big a task you hand over. A task that produces one revertable change produces one clean commit almost by accident. A task described as "improve the profile page" produces the blob above, every time.

Splitting a mess afterwards works (git add -p, or asking the agent to rebase it into pieces), it just costs a session to rebuild intent that was free to record live.

The agent knows what changed. You know why.

Give agents credit: they read the diff before writing about it, so their subject lines beat what a tired human types at 18:30. Simon Willison's notes on using git with coding agents go further: ask for commits to be reorganized and the model will do it.

What it cannot know is why. The constraint you gave verbally, the approach you rejected in the first ten minutes, the customer report behind the whole thing: none of that is in the diff, so none of it reaches the repo unless you put it there.

So split the job. Subject line from the diff, body from the brief. The body carries three things worth having at midnight: why this happened now, what was considered and dropped, and what to check first if it breaks. One line each is plenty.

Then hold one hard rule: the message may never claim more than the diff does. Reading the subject next to git show --stat costs a second and is the cheapest verification step in the whole workflow. To enforce it rather than remember it, that is the job of a hook: block the commit command when it carries -A or -a, and let the pathspec form through.

Commit hygiene when several agents share one repo

Run more than one session in a tree and git add -A stops being sloppy and starts being dangerous. It sweeps up whatever the other agent has half-written, so your commit carries work you have never read, filed under a task it has nothing to do with. Revert it later and someone else's afternoon goes with it.

Three habits keep parallel work honest. Branch per task, ideally with a worktree per agent so the trees cannot mix in the first place. Stage by pathspec, naming the files the task owns instead of everything that happens to be dirty. And one merge per task, so the branch stays the unit you review, in the way reviewing agent output already assumes.

Where commit discipline goes wrong

The obvious failure is the opposite of the blob: fourteen commits called "wip", each one a keystroke of progress. Bisect needs every commit to build, and a checkpoint dropped mid-refactor does not, so that history makes git bisect answer "skip" until you give up on it. Checkpoint freely while working, squash before merging.

The expensive failure is rewriting. Agents are fluent with --amend, interactive rebase and force-push, and fluent plus unsupervised is how a commit you already reviewed becomes a different one, or how an hour of work stops existing. Rewriting shared history should be human-only, denied at the permission layer rather than discouraged in prose.

Then the boring one: git add -A commits .env, build output and a 40MB fixture directory. Rotating the leaked key is the cheap part.

The cost runs both ways, though. Commit discipline spends tokens and adds a beat between steps, and for a throwaway spike it is ceremony. If nothing in the session will ever need reverting, skip all of it.

A desk where the card is the commit boundary

That is the part SanuDesk was built around. It is a desktop app for running Claude Code, Codex and Gemini sessions side by side: they tile into one grid, so you can see which agent is mid-commit instead of finding out afterwards.

Next to the grid sits a Kanban board, and that is where the boundary gets set. You write a card scoped to one change, deploy it to a fresh session with a click, and the scope on the card becomes the scope of the commit. When the agent stops, the card lands in a review lane with a what-changed note you read straight against git log. Recurring checks become a Loop: a weekly pass listing every commit from the last seven days that touched more than fifteen files, journaled so the trend stays visible. It drives the model subscriptions you already pay for, and the grid and board are in the free plan (see pricing).

Run one command tonight

Point this at the last week of agent work:

git log --oneline --stat --since='7 days ago'

Count the files per commit, take the largest one, and ask the only question that matters: could you revert exactly that change tomorrow without taking anything else with it? If not, add the three commit clauses above to your agent instructions file before the next session starts. It is a ten-second check that decides how expensive your next incident is.

Download SanuDesk free to keep one card, one session and one commit pointing at the same change, or see how the grid, the board and Loops fit together on the features page.

Run your own fleet of agents

SanuDesk is a free desktop app that tiles your Claude Code and Codex sessions and gives every project a Kanban board your agents work from.