All labsLab 04
Level 220 min+100 XP

Undo Anything: Git, Checkpoints & Rewind

Twenty minutes of breaking your own project on purpose, so that approving a change stops costing you anything.

After this module you can

undo any bad agent change three different ways, and name the damage that none of the three can reach

You need
  • 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.

100most recent checkpoints keep file snapshotsClaude Code docs · checkpointing ↗
~30 daysthen those snapshots expire (cleanupPeriodDays)Claude Code docs · checkpointing ↗
93%of permission prompts get approvedAnthropic, 25 Mar 2026 ↗

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

  1. 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.

    terminal — right window
    cd qairu-event
    git status
    git log --oneline

    If git status shows anything modified, save it now. The message does not have to be beautiful.

    terminal — right window
    git add -A
    git commit -m "save point before lab 04"

    The top line of git log --oneline is 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:

    terminal — left window
    claude --permission-mode manual
  2. Break 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.

    Breakage 1 — committed damageClaude Code · manual mode
    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.

    terminal — right window
    git log --oneline

    A new line sits on top: restyle. The damage is in your history now, which rules out layers two and three.

  3. Undo #1 — git revert, the one that is safe in front of other people

    terminal — right window
    git revert --no-edit HEAD
    git log --oneline

    Reload the browser: the page is back. But git log is now one line longer, not one line shorter. git revert erased 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-edit skips the text editor. For an older commit, pass its short hash: git revert --no-edit <hash>.

  4. Break it again — this time, do not let it commit

    Breakage 2 — uncommitted mess, plus a file you never asked forClaude Code · manual mode
    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.

    terminal — right window
    git status
    git diff --stat

    index.html sits under “Changes not staged for commit”. scratch-notes.md sits under “Untracked files”. Remember the difference.

  5. Undo #2 — throw the uncommitted mess away

    terminal — right window
    git restore .
    git status

    index.html is clean. scratch-notes.md is still sitting there: git restore only restores files git already tracks.

    For untracked leftovers, look before you shoot. -n prints what would go and deletes nothing.

    terminal — right window
    git clean -nd

    scratch-notes.md should be the only thing on that list. Now delete it for real: -f is what makes it happen.

    terminal — right window
    git clean -fd
    git status

    One case defeats git restore: if you or the agent already ran git add, the bad change sits in the staging area, and git 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.

    terminal — right window
    git reset --hard HEAD
    git status
  6. Undo #3 — rewind, without touching git at all

    First, the cheaper move that comes before any undo: while Claude is mid-answer, press Esc once. 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.

    Breakage 3 — pure edit-tool damageClaude Code · manual mode
    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 Esc twice (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:

    terminal — right window
    git status

    Nothing 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 with claude --continue --fork-session: same history behind you, two futures in front of you (checkpointing).

  7. Find the undo that does not exist

    The most important step in this lab, and it takes ninety seconds.

    The side effectClaude Code · manual mode
    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 Esc Esc and restore the code to before that prompt. Then look in the right window:

    terminal — right window
    git status

    agent-was-here.txt is 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:

    terminal — right window
    git clean -nd

    One file on the list, and it is the one you expected. Now for real:

    terminal — right window
    git clean -fd
  8. Finish clean, then write the rule down

    terminal — right window
    git status
    git log --oneline

    A 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:

    Teach it the habitClaude Code · any mode
    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.

Quick check

You ask Claude to tidy the project. It uses a shell command to move about.html into a new pages/ folder, then uses its edit tool to update the links in index.html. You hate the result, press Esc Esc, and choose 'Restore code and conversation'. What is on disk now?

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

Panic promptClaude Code · paste this when you have already broken something
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.

Before you let an agent loose again0/5 done
Take it with you · cheatsheetThe three-layer undo card

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.

You are done when

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.