Undo Anything: Git, Checkpoints & Rewind
Twenty minutes of breaking your own project on purpose, so that approving a change stops costing you anything.
undo any bad agent change three different ways, and name the damage that none of the three can reach
- A folder with a git history — the QAIRU Event Sign-up page from Lab 02, or any project with at least one commit
- Claude Code installed and logged in (Lab 01)
- git on your PATH — on Windows, install Git for Windows first
Most people slow down with an agent for one reason: every approval feels like a one-way door. It is not. Spend twenty minutes breaking your own project on purpose — three kinds of damage, three ways back — and from then on the door swings both ways.
This is not a git tutorial. It is a nerve tutorial. Anthropic reports that Claude Code users approve 93% of permission prompts, and names the result: “approval fatigue, where people stop paying close attention” (Anthropic, 25 Mar 2026). You will not read every diff forever. So the skill that actually keeps you safe is not vigilance — it is recovery.
Three layers, and the question that picks between them
| Layer | Brings back | Leaves alone | Where you type it |
|---|---|---|---|
Rewind — Esc Esc or /rewind |
files that Claude’s own edit tools changed in this session, plus the conversation | anything a Bash command touched, most subagent edits, your own manual edits, anything remote | inside Claude Code, as a menu |
git restore / git reset --hard |
tracked files, back to your last commit | new untracked files, and anything already committed | your terminal |
git revert |
a commit that is already in history, by writing its opposite as a new commit | work you never committed | your terminal |
One question sorts almost every emergency: did it get committed? If yes, git revert. If no, git restore or git reset --hard. If it is still inside the same Claude session and only the edit tools were involved, rewind beats both — and it hands your prompt back so you can fix the wording and try again.
Rewind is a session convenience with an expiry date. Git is the floor you land on. Never let an agent work in a folder git does not know about (checkpointing).
Break it three times, bring it back three times
Open two windows and make a save point
Left window: Claude Code. Right window: a plain terminal in the same folder. Keep both open for the whole lab: you want to watch the repo change while the agent works.
cd qairu-event git status git log --onelineIf
git statusshows anything modified, save it now. The message does not have to be beautiful.git add -A git commit -m "save point before lab 04"The top line of
git log --onelineis now your starting point. Everything you do for the rest of this lab lands above it.In the left window, start the agent in Manual mode so every action is visible before it runs:
claude --permission-mode manualBreak it on purpose, and let the damage reach a commit
Give Claude something you genuinely do not want, and let it save the result. Approve each step.
Rewrite index.html so that every heading is in ALL CAPITAL LETTERS, replace the seat counter with the word "SOON", and delete the text labels on the sign-up form inputs. Then commit the change with the message "restyle".Open the page in a browser. It is worse, and the form is now unusable for anyone on a screen reader. Good.
git log --onelineA new line sits on top:
restyle. The damage is in your history now, which rules out layers two and three.Undo #1 — git revert, the one that is safe in front of other people
git revert --no-edit HEAD git log --onelineReload the browser: the page is back. But
git logis now one line longer, not one line shorter.git reverterased nothing. It read the bad commit, worked out its exact opposite, and saved that opposite as a new commit on top.That sounds worse than deleting the mistake. It is better: once anyone else has a copy of a commit, rewriting history breaks their clone, while adding one never does.
--no-editskips the text editor. For an older commit, pass its short hash:git revert --no-edit <hash>.Break it again — this time, do not let it commit
Change the page background to hot pink, add a giant "SOLD OUT!!!" banner above the form, and create a new file called scratch-notes.md with your reasoning. Do not commit anything.Approve it. Now you have two problems in one folder: a tracked file that was modified, and a brand-new file git has never seen. They need different commands, and this is where beginners lose time.
git status git diff --statindex.htmlsits under “Changes not staged for commit”.scratch-notes.mdsits under “Untracked files”. Remember the difference.Undo #2 — throw the uncommitted mess away
git restore . git statusindex.htmlis clean.scratch-notes.mdis still sitting there:git restoreonly restores files git already tracks.For untracked leftovers, look before you shoot.
-nprints what would go and deletes nothing.git clean -ndscratch-notes.mdshould be the only thing on that list. Now delete it for real:-fis what makes it happen.git clean -fd git statusOne case defeats
git restore: if you or the agent already rangit add, the bad change sits in the staging area, andgit restore .copies it straight back into your files. The hammer for that case throws away the staged and the unstaged version of every tracked file at once, back to your last commit. Run it now — your tree is already clean, so it costs you nothing and you learn where the command lives.git reset --hard HEAD git statusUndo #3 — rewind, without touching git at all
First, the cheaper move that comes before any undo: while Claude is mid-answer, press
Esconce. It stops and keeps the work already done. Half a wrong change is easier to fix than a whole one.Now break the page a third time and take it back from inside the session.
Rename every CSS class in index.html to a single letter to save bytes. Do not commit.Approve it, then look at what it did to a file you have to maintain. Now, with an empty input box, press
Esctwice (or type/rewind).A menu opens listing your prompts — every prompt that starts a turn creates a checkpoint. Six choices appear: Restore code and conversation, Restore conversation, Restore code, Summarize from here, Summarize up to here, Never mind.
Select the CSS-renaming prompt and choose Restore code and conversation. The file goes back, and that prompt reappears in your input box, so you can fix the wording rather than retype it. Confirm it from the outside:
git statusNothing modified. You just undid an agent’s work without a single git command.
Go deeperTry an idea without losing the session you are in
Rewind moves you backwards along one line. To test an alternative and keep the original conversation intact, the docs point at
/branch, or restarting withclaude --continue --fork-session: same history behind you, two futures in front of you (checkpointing).Find the undo that does not exist
The most important step in this lab, and it takes ninety seconds.
Using a shell command, not your edit tool, create a file called agent-was-here.txt containing today's date. Then stop.Approve the Bash call. (If Claude reaches for its edit tool anyway, reply:
run it as a shell command, not with your edit tool.)Now press
EscEscand restore the code to before that prompt. Then look in the right window:git statusagent-was-here.txtis still there. Rewind restored nothing, because checkpoints snapshot what Claude’s edit tools touch — not files created, moved or deleted by a Bash command, not most subagent edits, not edits you made yourself in another editor, and nothing that left your machine.Clean it up yourself, which is the whole point. Dry run first, same as before:
git clean -ndOne file on the list, and it is the one you expected. Now for real:
git clean -fdFinish clean, then write the rule down
git status git log --onelineA clean working tree. Above your starting point, two lines: the breakage, and the revert that cancelled it. Git keeps the mistake and the fix side by side, on purpose. Everything else you did today left no trace.
Last thirty seconds — turn this into a standing rule, in the memory file from Lab 03:
Add this to CLAUDE.md, in the existing rules section, in one line: before starting any change that touches more than two files, stop and tell me to commit first.Approve the edit and commit CLAUDE.md. Next week the agent reminds you, instead of the other way round.
The damage that has no undo
Three layers cover your files. They cover nothing beyond your files.
Go deeperYou reset too far and lost a commit. Try git reflog.
git reflog prints every position your branch tip has been in recently, including ones you just threw away. Find the line from before the mistake, copy its hash, then git reset --hard <hash> to go back, or git checkout -b rescue <hash> to park it somewhere safe and look first.
The limit is exact: reflog only knows about commits. Work that was never committed was never written down anywhere, so nothing finds it.
Lock it in
I need to undo something. Do not change any files yet.
1. Run `git status` and `git log --oneline -5` and show me the raw output.
2. Tell me which of these describes my situation:
(a) the bad change is already committed
(b) the bad change is uncommitted
(c) both, plus new files I never asked for
3. For my case, give me the exact commands in the order I should run them,
and for each one say what it deletes permanently.
4. Tell me what git cannot recover here, if anything.
Then stop and wait. I will run the commands myself.Save that one. Asking the agent to explain the recovery while you type the commands yourself is the right division of labour for anything destructive.
Committed, uncommitted, or still in the session — the one question that picks your recovery, the exact commands for each, and the short list of damage that no undo reaches.
Your project is back at a clean, committed state after three deliberate breakages, and you can name one kind of change that a rewind will never bring back.