Skip to content

How to Set Up Automatic Git Commit and Revert on Failure in AI Coding Workflows

Problem

When I use AI to help with coding, I often end up with a mess. The AI makes a change, something breaks, then it makes another change to fix that break, which breaks something else. After 10 minutes, I have a tangled mess of broken code and no idea how to get back to a working state.

Here’s what happened in one session:

AI: Let me fix the import error.
[Changes 3 files]
AI: Now let me fix the type error.
[Changes 2 more files]
AI: There's a test failing.
[Changes another file]
Me: Wait, the original feature is broken now.
AI: Let me fix that.
[Changes 4 files]
Me: Stop! I just want to go back to before this started.

At this point, I have 10 uncommitted changes, no working tests, and no clear way to undo just the broken parts. The AI tried to be helpful, but each fix created new problems that compounded.

What happened?

I was using AI in a naive way: let it make all the changes it wants, then deal with the aftermath. This works fine for simple tasks, but for complex refactoring or multi-file changes, it creates a cascade of problems.

The issue is that AI doesn’t naturally work in an atomic way. It sees a problem, fixes it, sees another problem, fixes that too. Without a rollback mechanism, errors stack on top of each other.

I found a Reddit discussion where developers shared a better pattern for AI coding workflows. The key insight: treat each AI action as an atomic unit that must pass verification before it sticks.

The Atomic Pattern

The pattern is simple but powerful:

┌─────────────────────────────────────────────────────────┐
│ Make ONE atomic change │
│ ↓ │
│ git commit immediately │
│ ↓ │
│ Run verification tests │
│ ↓ │
│ ┌─────────────┐ │
│ │ Tests pass? │──Yes──→ Keep the commit │
│ └─────────────┘ │
│ │ │
│ No │
│ ↓ │
│ git revert HEAD (auto-rollback) │
└─────────────────────────────────────────────────────────┘

This pattern ensures two things:

  1. Every improvement stacks - Good changes are saved
  2. Every failure auto-reverts - Bad changes disappear

How to implement this?

Let me show you how I set this up in my workflow.

Step 1: Create a verification script

First, I created a script that runs my verification checks:

verify.sh
#!/bin/bash
set -e
# Run linting
npm run lint
# Run tests
npm test
# Run type checking
npm run typecheck
echo "All checks passed!"

This script returns exit code 0 if everything passes, non-zero if anything fails.

Step 2: Create the atomic workflow script

Then I created a script that wraps the commit-and-verify pattern:

atomic-commit.sh
#!/bin/bash
COMMIT_MSG="$1"
if [ -z "$COMMIT_MSG" ]; then
echo "Usage: ./atomic-commit.sh 'commit message'"
exit 1
fi
# Check if there are changes to commit
if git diff --quiet && git diff --staged --quiet; then
echo "No changes to commit"
exit 0
fi
# Commit the changes
git add -A
git commit -m "$COMMIT_MSG"
# Store the commit hash for potential revert
COMMIT_HASH=$(git rev-parse HEAD)
# Run verification
echo "Running verification..."
if ./verify.sh; then
echo "Verification passed. Commit kept: $COMMIT_HASH"
else
echo "Verification failed. Reverting commit..."
git revert --no-edit HEAD
echo "Commit reverted. Check the error output above."
exit 1
fi

Step 3: Use it in AI coding sessions

Now when I work with AI, I ask it to make small, focused changes and run this script after each one:

Me: Add error handling to the fetchUserData function. Use atomic-commit.sh after.
AI: [Makes the change]
Running verification...
✓ Lint passed
✓ Tests passed
✓ Type check passed
Verification passed. Commit kept: abc1234

If verification fails:

Me: Refactor the auth module. Use atomic-commit.sh after.
AI: [Makes the change]
Running verification...
✓ Lint passed
✗ Tests failed: 2 tests failing
Verification failed. Reverting commit...
Commit reverted. Check the error output above.

The broken changes are gone. I’m back to a clean state.

Why this works

I think the key reasons this pattern works are:

1. Small atomic changes are easier to debug

When a change fails, I know exactly which commit caused the problem. I don’t have to hunt through 10 files of changes.

2. Rollback removes the temptation to “just fix it”

Without rollback, I’d be tempted to let the AI keep fixing the broken tests it created. With rollback, I’m forced to step back and reconsider the approach.

3. Clean state means clean context

AI works better with clean context. When I revert a bad change, the AI doesn’t have to reason about broken code that shouldn’t exist.

4. Each commit is a checkpoint

If I realize later that a change was wrong, I can use git revert on that specific commit. The history is clean and navigable.

Common mistakes I made

Mistake 1: Making changes too large

At first, I asked the AI to “refactor the entire module” in one atomic commit. This often failed because the change touched too many things at once. I learned to break large tasks into smaller pieces:

# Too large
"Add error handling to all API endpoints"
# Better - break into atomic pieces
"Add error handling to the user endpoint"
"Add error handling to the product endpoint"
"Add error handling to the order endpoint"

Mistake 2: Verification that’s too slow

My initial verification script ran the entire test suite, which took 5 minutes. This made the atomic workflow painful. I split verification into two levels:

verify-quick.sh
#!/bin/bash
# Quick verification for small changes
npm run lint
npm run test -- --related --bail
npm run typecheck

Quick verification runs in seconds. Full verification runs before pushing.

Mistake 3: Forgetting to commit before verification

Sometimes I’d run the AI, it would make changes, and I’d forget to use atomic-commit.sh. Then something would break and I’d have uncommitted changes with no clean rollback. I added a pre-check to remind myself:

atomic-commit.sh (improved)
# Check for uncommitted changes from previous sessions
if ! git diff --quiet || ! git diff --staged --quiet; then
echo "WARNING: You have uncommitted changes."
echo "Run this script after each AI change to keep your history clean."
read -p "Continue anyway? (y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi

Using with Claude Code

If you use Claude Code, you can set up a hook to automate this. In your CLAUDE.md:

CLAUDE.md
## Atomic Change Rule
**Trigger:** After making code changes
**Action:**
1. Stage all changes with git add
2. Commit with descriptive message
3. Run verification (lint, test, typecheck)
4. If verification fails, revert the commit and explain the failure

This makes the atomic pattern automatic. Claude will commit, verify, and rollback without you having to ask.

Summary

In this post, I showed how to set up automatic git commit and revert on failure in AI coding workflows. The key point is the atomic pattern: make one small change, commit immediately, verify, and automatically revert if tests fail. This prevents error accumulation and keeps your codebase in a clean, working state.

The rollback-on-failure piece is the most underrated part of this pattern. Without it, errors stack on top of each other until you lose track of what broke and when. With it, you get a clean slate after every failed attempt, and your git history tells a clear story of what worked.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments