Atomic commits for AI agents

4 min read Original article ↗

These days I hardly write commit messages manually anymore. The agent, with all the context on the task, writes reasonably good commit messages in a fraction of the time I would.

Where agents occasionally struggle, however, is atomic commits - commits that contain exactly one logical change. If at any point unrelated changes are introduced into the same file, not to mention within close proximity of each other, the agent will have to go through unreasonable hoops to separate them, or just lump everything into one commit.

This is mainly a tooling issue. Interactive git commands like git add -p don't work well for agents (except in trivial cases). When asked to commit changes separately, they may decide it's easier to start from scratch:

❯ commit the changes separately

⏺ Bash(git diff internal/bot/listing_handler.go)
  ⎿  diff --git i/internal/bot/listing_handler.go ...
     ... +83 lines

⏺ Let me reset and make the changes in two separate commits.

⏺ Bash(git checkout internal/bot/listing_handler.go)   ← about to destroy changes
  ⎿  Interrupted

The agent's instinct here is to check out the file, resetting all changes, then manually re-apply and commit them in separate steps.

#Enter git-surgeon

Recently I got tired of watching agents fumble with this, so I built git-surgeon. It exposes non-interactive primitives for hunk-level git operations. Each hunk gets a stable ID that the agent can reference to stage, unstage, discard, or commit specific changes.

❯ commit the changes separately

⏺ I'll commit these as separate changes using git-surgeon.

⏺ Skill(git-surgeon)
  ⎿  Successfully loaded skill

⏺ Bash(git-surgeon hunks)
  ⎿  ac34353 internal/bot/listing_handler.go (+6 -3)
     15baf94 internal/bot/listing_handler.go (+10 -2)
     ...

⏺ Bash(git-surgeon commit ac34353 15baf94 -m "allow edit commands during attribute input")

⏺ Bash(git-surgeon commit 4eefac8 bbba931 -m "add logging for attribute prompts")

For commits that already mixed concerns, there's a split command that breaks them into focused commits - selecting hunks by ID, or specific lines when a hunk itself mixes changes:

❯ split the big pagination commit that mixes concerns into multiple commits

⏺ Skill(git-surgeon)
  ⎿  Successfully loaded skill

⏺ I'll help you split the pagination commit. Let me first look at the commit
  history to identify it, then examine its hunks.

⏺ Bash(git log --oneline -5)
  ⎿  dda5d0e add readme
     945381f add pagination, logging, and active user filtering
     386b2fe initial app setup

⏺ Bash(git-surgeon hunks --commit 945381f --full)
  ⎿  a811273 config.py (+3 -1)
       4:-LOG_LEVEL = "INFO"
       5:+LOG_LEVEL = "DEBUG"
       6:+LOG_FORMAT = "%(asctime)s %(name)s %(levelname)s %(message)s"
       7:+MAX_PAGE_SIZE = 100

     37562e9 models.py (+11 -2)
       2:-    def __init__(self, id, name, email):
       3:+    def __init__(self, id, name, email, active=True):
       ... +12 lines

     8c1940f server.py (+19 -4)
       2:+import logging
       5:+logging.basicConfig(level="INFO")
       6:+logger = logging.getLogger(__name__)
       ... +16 lines

⏺ I can see the commit mixes several concerns:
  1. Logging - LOG_LEVEL, LOG_FORMAT, logging imports, logger calls
  2. Pagination - MAX_PAGE_SIZE, pagination logic in list_users
  3. Active user filtering - active field in User model and data

  Let me split this into three focused commits:

⏺ Bash(git-surgeon split 945381f \
       --pick a811273:4-6 8c1940f:2,5-6,34,37 -m "add logging infrastructure" \
       --pick 37562e9:3,7,15 8c1940f:11-13,22 -m "add active flag to users" \
       --rest-message "add pagination support")
  ⎿  committed: add logging infrastructure
     committed: add active flag to users
     committed: add pagination support

The tool is built strictly for agents - terse output, no interactivity, token-efficient CLI. It ships with a skill that teaches your agent the commands, so you load the skill and (mostly) let it figure out the rest. At this point it's mostly an experiment and true value remains to be seen, but it sure feels satisfying seeing an agent use it.

git-surgeon

Surgical, non-interactive git hunk control for AI agents

Rust 6

Read next Introduction to workmux for parallelizing agent work across git worktrees.