
An AI coding agent writes code fast enough to make your old pace feel frozen. That speed turns destructive the moment the agent touches git without rules. Give the agent three rules before your next session: one branch per task, one logical change per commit, and no merge without your review. These rules keep history readable and rollbacks safe. I run every agent session this way, and the repos stay clean even when the agent writes thousands of lines in an afternoon. This guide is for developers who already let agents write code and want the version control to survive the experience.
Left alone, a coding agent treats version control as a save button. It finishes a long session, dumps everything into one commit named “update files”, and pushes. Or worse, it commits straight to main because nobody told it otherwise. I have opened logs that read like a cry for help: “changes”, “fix”, “wip”, then a 900-line diff across fourteen files.
A history like that costs you three times. At review time, no human can reconstruct what each change was for. At rollback time, reverting one broken feature means extracting it piece by piece from a commit that also contains five working ones. And when a session dies mid-task with nothing committed, the work is gone and the agent happily starts over from scratch. git bisect turns useless. Blame tells you the agent did it, which you already knew.
The agent is not being lazy. It optimizes for “task done”, and git history is not part of the task unless you say so. That is the core mismatch: you live in the history for months, the agent lives in the session for minutes. The fix is to make history part of the task, in writing, before the agent starts.
The trap is that messy history feels harmless while everything works. Nobody reads the log when the deploy is green. The bill arrives months later, during an incident, when you need to know exactly which change introduced the bug and the log answers with “update files”. By then the agent session is long gone and the context with it. Clean history is incident insurance, and it costs almost nothing if you set it up before the first prompt.
Every agent task starts on a fresh branch cut from main, with no exceptions and no quick fixes landing directly on main. The pattern looks like this:
git checkout -b agent/add-rate-limiting
Keep the branch name short and tied to the task. Prefix agent branches with agent/ so they stand out in the branch list and so stale ones are easy to spot during cleanup. Delete the branch when the task lands. Delete it too and start over when the agent goes off track and fills the branch with experiments you do not want. A branch is cheap; a polluted main is expensive.
This rule gives you a kill switch. An agent session that spirals produces a branch you can abandon in one command instead of a main branch you have to repair by hand. It also gives you parallel work for free: two agents on two branches with no interference.
Back the rule with branch protection. In the repo settings, require pull requests for main and reject direct pushes, so the rule holds even when the agent gets creative and tries to push where it should not. If your debugging workflow with AI assistants ever goes sideways, the same kill switch applies: drop the branch, keep main clean.
Ship one logical change per commit, and tell the agent to commit after each green test run instead of waiting for the end of the session. A feature that touches auth, the API client, and the docs becomes three commits, each reviewable on its own. Future you will thank present you the first time a revert takes ten seconds instead of ten minutes.
Compare the two messages below. The first tells you nothing; the second tells you everything you need for a revert decision:
update stuff feat(auth): add rate limiting to login endpoint
Use the Conventional Commits format: type(scope): description. Real examples:
feat(auth): add rate limiting to login endpoint fix(api): handle null response from payment gateway docs(readme): document new environment variables
The type tells the reader what kind of change this is at a glance. The scope tells them where. The description stays in imperative mood, present tense, under fifty characters, no period at the end. These are Chris Beams’ rules for great commit messages, and they work as well for agent-written history as for human-written history.
Ban the lazy messages in writing. Put “commit messages like update, fix, or wip are rejected” in your agent rules file so every session inherits the standard. Agents follow written constraints far better than implied ones. The git commit documentation covers the mechanics; your rules file covers the discipline.
One more constraint: the agent does not rewrite shared history. Keep force-push off branches other people use. Revert a bad commit with a new commit instead of erasing it. History stays append-only, and every mistake stays visible and learnable.
Set a commit cadence the agent can follow without asking. “Commit after each green test run” works because the test result is an objective trigger the agent already understands. Each commit then bundles the code change with its passing tests, which keeps every commit deployable on its own. A repo where each commit passes tests is a repo you can bisect with confidence, and bisect is the tool that turns a mysterious regression into a ten-minute investigation.
The agent opens the pull request. You merge it. This division is the whole game: the agent does the labor, you keep the authority. GitHub’s pull request flow gives you the review surface; the rule gives it teeth.
Require a real PR body from the agent. The body covers what changed and the tests the agent ran, with a short note on anything risky. Risky means database migrations, auth changes, and dependency upgrades: the changes that break quietly. An agent that writes “implemented the feature” as the entire description has not finished the task. Send it back. The PR description is where the agent proves it understood the work, and it takes thirty seconds to read.
Make CI the second reviewer. Status checks must pass before merge, every time. If you want the full routine, my guide to testing AI-generated code before you ship covers the test layer this rule assumes. Protect main with required reviews and required checks, and the agent cannot merge its own work.
When a PR falls short, use the review loop instead of fixing it yourself. Request changes on the PR, describe what is missing, and let the agent push new commits to the same branch. The habit you want is a conversation in the PR, not a rescue mission in your editor. After two rounds of fixes with no improvement, stop and take the task back: some tasks need a human driver, and the PR thread will show you exactly where the agent got lost.
The difference the three rules make, in one table:
| Area | Default agent behavior | With these rules |
|---|---|---|
| Branching | Works on main or a stale branch | Fresh branch per task, cut from main |
| Commits | One giant commit at the end, message “updates” | Small commits per logical change, typed messages |
| History rewrites | Force-pushes to fix mistakes | Append-only; bad commits get reverted |
| Push target | Pushes to main when convenient | Main rejects direct pushes; PRs only |
| Pull requests | Opens PR with empty description, or none | PR carries summary, test plan, risk notes |
| Rollback | Hunt through a 900-line diff | Revert one small commit |
Rules only work if the agent reads them. Paste this block into your agent’s instructions at the start of a task, or save it as a reusable file:
1. Create a new branch for this task named agent/short-task-name, cut from main. 2. Commit after each logical change, not at the end of the session. 3. Write commit messages as type(scope): description. Imperative mood, subject under 50 characters. 4. Push the branch and open a pull request. Do not merge it yourself. 5. In the PR body include: summary of changes, test plan, anything risky. 6. Push only to your branch. Leave shared history alone.
Keep the block short. Agents follow short constraint lists; they skim long ones. If you already keep structured prompt files for complex work, this block belongs in the git section of that file.
AI coding agents will keep getting faster, and vibe coding will keep tempting you to skip the boring parts. Git history is not a boring part. It is the record your future self reads when something breaks at the worst possible moment.
The system is three rules, enforced in writing: one branch per task, small commits with real messages, pull requests merged by humans. Add the prompt block to your agent setup today and run one task end to end. Then read the log. If every commit tells you what changed and why, the system works. If it does not, tighten the prompt and run it again. Clean history is a habit, and habits are rules you stopped negotiating with.