DEV Community

Vishal Chauhan
Vishal Chauhan

Posted on

How to Stop AI From Breaking Your Working App: A 7-Step Git Safety Net for Vibe Coders

You ask your AI coding tool for one small change. It edits twelve files, login stops working, and you can't remember what the code looked like an hour ago. The fix isn't a smarter model. It's a safety net that lets you undo a bad AI change in seconds.

This guide sets one up with Git (the free version-control tool) plus a short rules file that tells your AI what not to touch. It works whether you build in Cursor, Claude Code, Codex, or sync code out of Lovable or Replit. Plan on about 30 minutes, once.

Quick jargon guide:

  • Repo (repository): your project folder, with Git tracking its history.
  • Commit: a saved snapshot of your project. Think "save point in a game."
  • Diff: a line-by-line view of what changed since the last snapshot.
  • Branch: a parallel copy of your project where you can experiment without touching the main version.

Why your AI tool's built-in undo isn't enough

Most AI tools have their own checkpoints, and they're useful for quick undos. But read the fine print:

  • Claude Code checkpoints don't track files changed by shell commands like rm or mv. Its docs call them "not a replacement for version control."
  • Cursor checkpoints are stored locally, separate from Git, and its docs say to use Git for permanent version control.
  • Replit checkpoints also create Git commits, but database rollback is optional and production databases aren't restored automatically.

So treat built-in checkpoints as the quick "oops" button and Git as your real history.

Step 1: Turn your project into a Git repo (without committing secrets)

Open a terminal in your project's root folder. Before your first commit, create a .gitignore file so Git never saves your secrets or giant dependency folders. These lines come from GitHub's official Node template:

node_modules/
.env
.env.*
!.env.example
Enter fullscreen mode Exit fullscreen mode

Then create the repo and your first snapshot:

git init -b main
git status
git add -A
git commit -m "checkpoint: app works before AI changes"
Enter fullscreen mode Exit fullscreen mode

Check the git status output before git add. If .env is listed, your .gitignore isn't working yet. Fix that first.

If a secret file is already committed, GitHub's docs say to untrack it with git rm --cached FILENAME first. Treat any key that was ever pushed as exposed and rotate it.

Step 2: Back it up off your laptop

A repo that only lives on your laptop dies with your laptop. Push it to a private GitHub repository. With the GitHub CLI installed and logged in:

gh repo create --source=. --private --push
Enter fullscreen mode Exit fullscreen mode

Or, after creating an empty repo on github.com (no README, license, or gitignore, as GitHub's docs advise):

git remote add origin REMOTE-URL
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

Building in Lovable? Connect GitHub under Project settings -> Git -> GitHub. Lovable creates a new private-by-default repository and keeps it in two-way sync. Don't delete that repo, or the sync stops.

Step 3: Use the checkpoint loop for every AI task

This is the habit that does most of the work. Before every prompt that changes code:

git add -A
git commit -m "checkpoint: before AI adds search bar"
Enter fullscreen mode Exit fullscreen mode

Then:

  1. Give the AI one task, not five.
  2. Test the result yourself.
  3. Works? Commit again with a message saying what changed.
  4. Broken? Undo it (Step 5) and try a smaller prompt.

Step 4: Read what the AI actually changed

Before you test, look at what changed:

git status          # every changed AND every brand-new file
git diff --stat     # which tracked files changed, and how much
git diff            # the exact lines added and removed
Enter fullscreen mode Exit fullscreen mode

One gotcha we confirmed while testing: git diff only shows files Git already tracks. New files the AI created show up in git status with ??, but not in git diff. Check both.

What to look for:

You see What it often means
A file you never mentioned The AI widened the scope on its own
Deleted or weakened tests It made the error disappear instead of fixing it
package.json changes A new dependency you didn't ask for
Config, auth, or payment files touched High-risk change; review line by line

If the diff is too big to read, the task was too big. Undo it and split it up.

Step 5: Undo the damage (the cheat sheet)

Pick the row that matches your situation. We ran every command below in a test repo with Git 2.47.

Situation Command
AI broke files, nothing committed yet git restore .
Only one file is bad git restore path/to/file.js
AI also created junk files git clean -nd (preview), then git clean -fd
You want one file as it was in an older commit git restore --source=COMMIT_ID path/to/file.js
Bad change already committed and pushed git revert COMMIT_ID
Bad commits only on your laptop git reset --hard COMMIT_ID

A few notes so you don't hurt yourself:

  • git restore . puts tracked files back to your last snapshot (if you haven't run git add on the changes yet) but leaves new untracked files alone. That's what git clean is for.
  • git clean -fd permanently deletes untracked files and folders. Always run the -n dry run first. Files listed in .gitignore, like .env, are left alone unless you add -x.
  • git revert adds a new commit that reverses an old one, so it's safe on pushed code. git reset --hard rewrites your branch and overwrites uncommitted work. Keep it for local-only mistakes.
  • Find a COMMIT_ID with git log --oneline.

Undid too much? Run git reflog. It lists where HEAD (your current position) has pointed recently, including commits you "lost" with a reset. By default Git keeps these entries for 90 days, or 30 days for entries no longer reachable from your branch. Copy the ID and restore from it.

Step 6: Branch for risky experiments and tag what works

Trying something big, like adding payments? Do it on a branch:

git switch -c try/stripe-checkout
# ...let the AI work, commit as you go...
git switch main                       # back to safety
git branch -D try/stripe-checkout     # throw the experiment away
Enter fullscreen mode Exit fullscreen mode

If the experiment works, merge it with git merge try/stripe-checkout while you're on main.

When a feature is solid, name that snapshot:

git tag working-login
Enter fullscreen mode Exit fullscreen mode

Now "go back to when login worked" is git restore --source=working-login . (then commit), instead of digging through commit IDs.

Step 7: Write a rules file so the AI stops repeating mistakes

Your AI starts every session with no memory of what broke last time. A rules file fixes that. The simplest option is AGENTS.md in your project root, an open format read by Cursor, Codex, GitHub Copilot's coding agent, Gemini CLI, and many others. Claude Code reads AGENTS.md when there's no CLAUDE.md (v2.1.277 or later). If you already have a CLAUDE.md, add the line @AGENTS.md to it to import the file. Cursor users can also use .cursor/rules/*.mdc files with alwaysApply: true.

Here's a starter template. Edit the bracketed parts:

# AGENTS.md

## Project
- [One sentence: what the app does and who it's for]
- Stack: [e.g. Next.js, Supabase, Stripe]
- Run locally: `npm run dev`. Run tests: `npm test`

## Working rules
- Do one task per request. Change only the files the task needs.
- Before editing, list the files you plan to change and wait for my OK.
- Never delete or weaken tests to make them pass.
- Do not add new dependencies without asking.
- Do not touch: [e.g. src/auth/, supabase/migrations/, .env files]

## Git rules
- Do not commit, push, rebase, or force-push unless I ask.
- Never run `git reset --hard`, `git clean`, or `rm -rf` without asking.

## Known pitfalls
- [Add a line each time the AI makes the same mistake twice]
Enter fullscreen mode Exit fullscreen mode

Keep it short: Claude Code's docs suggest under 200 lines per file, Cursor's under 500 lines per rule. Both treat these files as guidance, not enforcement. The rules file reduces mistakes; Git catches the rest.

Copy-paste prompt: let your AI set this up

Make a checkpoint commit first (or copy your folder if you have no Git yet). Paste this into Cursor, Claude Code, or any agent, with the Step 7 template pasted right under it:

Set up a Git safety net for this project. Do these steps in order
and stop to show me the output after each one:
1. Create or update .gitignore so it ignores node_modules/, .env,
   and .env.* but keeps .env.example.
2. If this folder is not a Git repo, run `git init -b main`.
3. Run `git status` and show me the list. If any .env file or
   secret appears, stop and tell me instead of continuing.
4. Create AGENTS.md in the project root using the template pasted
   below. Fill in the stack and run commands by reading
   package.json. Do not invent commands that don't exist.
5. Do not commit. I will review and commit myself.
Apart from .gitignore and AGENTS.md, do not create, delete, move,
or rewrite any files.
Enter fullscreen mode Exit fullscreen mode

Common mistakes

  • Committing before adding .gitignore. Your .env ends up in history. Create .gitignore first.
  • Committing once a day. One giant commit can't separate good AI changes from bad ones.
  • Trusting git diff alone. It hides brand-new files. Check git status too.
  • Running git clean -fd without -n first. It deletes untracked files for good.
  • A huge rules file. Long files get followed less. Add a rule only when a mistake repeats.
  • Letting the AI commit and push for you. You lose the review step, which is the whole point.

Your safety net checklist

  • [ ] .gitignore covers node_modules/ and .env files
  • [ ] git init done and the first commit saved
  • [ ] Private GitHub repo created and pushed (or Lovable Git sync on)
  • [ ] Checkpoint commit before every AI task
  • [ ] git status and git diff checked after every AI task
  • [ ] Risky features built on a branch
  • [ ] Known-good states tagged
  • [ ] AGENTS.md in the project root with a "do not touch" list

Action summary

Today: add .gitignore, run git init, make your first commit, and push to a private GitHub repo. Tomorrow: create AGENTS.md from the template with your "do not touch" folders. From then on, run the loop on every AI task: commit, prompt, review the diff, test, then commit or restore. Keep the Step 5 cheat sheet in a tab, and an AI mistake becomes a five-second fix instead of a lost weekend.

Top comments (1)

Collapse
 
yi_zhao_a2633e86f8c799b5b profile image
yi zhao •

Great list — Step 7 is the one I'd underline twice. One addition from building in this space: a rules file is passive memory. It works when the agent reads it, remembers it, and the file stays short enough to stay in context.

I built provLedger (Claude Code plugin, MIT) around the complementary idea: instead of hoping the agent consults the record, a hook surfaces the relevant "why" — including paths that were tried and rejected — before each edit. Every claim cites its record id, and when nothing was recorded it says so instead of inventing one.

Rules files tell the agent what not to do in general. A decision ledger tells it what this project already tried, specifically, at the moment it's about to try it again. They stack well together.