Blog

How to undo changes in Claude Code: /rewind and git

Markdown

Rewind modes, checkpointing limitations, git checkout, stash, reflog, and protection against destructive commands. Five ways to restore a state.

Read full article

Practical information about working with Ailoot is available in the documentation.

What is undo in Claude Code, and why aren't three levels enough?

Key points

Undo in Claude Code has three levels: the built-in /rewind command (instant recovery within a session), git checkout (restore to the last commit), and git reflog (a catastrophic safety net if someone ran git reset --hard). Each level covers its own class of errors and nothing beyond its boundaries. Knowing only /rewind means being left with your pants down at the first serious screw-up.

I enabled /rewind in my first week of using Claude Code, when it broke my project's auth logic in two prompts. I rewound, exhaled, and carried on. A month later, another situation came up: I was writing a schema migration, Claude helped, I committed, switched branches—and realized I had forgotten a necessary step. /rewind didn't help—the session was already different. git checkout to the previous commit helped. A month after that, I accidentally told the agent, “roll everything back to the last push,” and it ran git reset --hard, wrecking three hours of work. git reflog saved me—the hashes of the destroyed commits were still there.

Those three stories are three levels of protection that work differently, catch different errors, and are all needed. This guide explains each level with its commands, limitations, and examples, plus shows how to configure a project in advance so Claude doesn't take it down the first time.

3 levels of undo—what and when:

LevelCommandCoversDoes NOT cover
1. Within a session/rewind or Esc EscFiles changed by Claude through its own tools; conversation historyBash commands, external editors, database migrations
2. Before a commitgit checkout . or git stashAll uncommitted changes to filesCommitted commits
3. Disastergit reflog + git reset --hard <hash>Commits destroyed by reset --hard or force-pushDestructive bash commands (rm, database migrations)

Next, we’ll go through each level—what exactly to do, the pitfalls, and how to configure things so there's nothing to undo because nothing broke.

How do you invoke /rewind: command or Esc-Esc?

Key points

There are two ways to open the Rewind menu in Claude Code. The first is to type /rewind in the input field. The second is to press Esc twice when the input field is empty. If there is text in the field, double Esc first clears it and saves its contents to input history; another double press opens the menu. The /rewind command is aliased to /checkpoint.

After every response, Claude automatically takes a snapshot of all files it edited in that session. Snapshots are stored in ~/.claude/file-history/{sessionId}/ and retained for up to 30 days. Snapshots are incremental—only the differences between states are saved, not the entire file. By default, up to 100 snapshots are stored per session. This means that in most real projects, you have a complete history of all of Claude's changes throughout the workday at any given moment.

To open the rewind menu, press Esc twice when the input field is empty:

[user-input is empty]
> _

[press Esc, Esc]

Rewind to which message?
  1. Create a migration for the User table          (3 files changed)
  2. Add the lastLoginAt field                      (1 file changed)
  3. Rewrite the authorization logic                (5 files changed)
  ...

If there is text in the input field, the first double press of Esc clears it and saves it in Up history. This is useful when you've already started typing and realize you need to rewind. A quote from Anthropic's official documentation:

If there is text in the prompt field, double Esc will first clear it rather than open the menu. The cleared text is saved in input history, so you can restore it with the up arrow after the rewind menu.

— Anthropic Docs, https://code.claude.com/docs/en/checkpointing

The /rewind command does the same thing—it opens the menu. There is an alias, /checkpoint, that leads to the same place. Which method is more convenient is a matter of habit. I use Esc Esc—it's faster and doesn't take my hands off the keyboard.

6 modes in the Rewind menu: which one should you choose, and when?

Key points

After selecting a rewind point in the Rewind menu, a second menu appears with six modes. Three restore state (Restore code and conversation, Restore conversation, Restore code), two compress history (Summarize from here, Summarize up to here), and one cancels the action (Never mind). The most common scenario—“rewind both code and conversation”—is the first option.

Choose a point in the list, and you’ll land in the actions menu. Six items, each doing something different.

Complete table of modes:

ModeWhat it doesWhen to choose it
Restore code and conversationRestores both files and conversation history to the selected pointThe most common scenario: Claude went in the wrong direction, and I want to start over with the right wording
Restore conversationRewinds only the conversation history; files remain as they are nowThe code is good, but the conversation went off track; I’ll rephrase from this point while preserving the current changes
Restore codeRewinds files; the conversation stays as it isSome of Claude’s changes were unnecessary, but I still need the conversation context (for example, we agreed on next steps)
Summarize from hereCompresses everything AFTER the selected point into a summary. Does not touch filesA long debugging session used up the context; I need to free up space while keeping the initial instructions in full
Summarize up to hereCompresses everything BEFORE the selected point into a summary. Does not touch filesThere was a long initial briefing followed by a specific task—we compress the briefing into one message and leave recent work as is
Never mindCloses the menu without changesI changed my mind

The Summarize up to here feature appeared in Claude Code v2.1.139-v2.1.142, released May 11–15, 2026, week 20:

You can compress early context through the Rewind menu using 'Summarize up to here'.

— Anthropic What's new, https://code.claude.com/docs/en/whats-new

The difference between Restore and Summarize is fundamental. Restore returns to a previous state, undoing everything that happened after the selected point. Summarize doesn't undo anything; it only compresses—the original messages remain in the session transcript for reference, but only the summary remains in active context. Use restore when you want it to be “as if this never happened.” Use summarize when you want to “keep it, but not take up context space.”

After Restore conversation or Summarize from here, the original text of the selected prompt returns to the input field—you can edit it and send it again. After Summarize up to here, the input field is empty, and you remain at the end of the conversation.

What changes does /rewind NOT undo?

Key points

/rewind tracks only changes made by Claude through its own file-editing tools. It can't see or restore anything else. There are three classes of invisible changes: bash commands (rm, mv, cp), external edits (your manual edits in an IDE, changes from other sessions), and operations outside files (database migrations, git push, remote API calls).

This is the main limitation people run into: /rewind shows a green check mark and says “rewind successful,” but the project is still broken because Claude touched more than just files. Let’s look at the three cases.

1. Bash commands are not tracked. If Claude runs rm file.txt or mv old.txt new.txt in a turn, those changes won't be included in the checkpoint. Anthropic's documentation states explicitly:

Checkpointing does not track files changed through bash commands. For example, if Claude Code runs rm file.txt, mv old.txt new.txt, cp source.txt dest.txt, these file changes cannot be undone through rewind.

— Anthropic Docs, https://code.claude.com/docs/en/checkpointing

This means that if Claude deletes, moves, or copies a file on its own using the bash tool, /rewind won't restore everything. git checkout or restoring from backup can help, but that takes more than pressing two keys.

2. External edits aren't caught. If you manually open a file in VS Code and edit something, or a second Claude session changes the same files in parallel, the first session can't see those changes. A checkpoint snapshot is taken when Claude finishes a turn in the current session. What happens between turns is outside its responsibility.

3. Operations outside files are not covered at all. A Prisma migration applied through npx prisma migrate dev changed the database schema—/rewind won't undo it because the database is outside the project's file system. A force-push to origin/main is the same: the commit went to the remote server, and the checkpoint won't bring it back. A remote API call that charged money or deleted a record can be undone only through the API's own mechanisms.

Rule: If a task affects anything outside the project files—database migrations, git push, remote APIs—prepare a separate rollback strategy for each external effect. /rewind is only the local file history within the current session.

/rewind vs git: how are they different, and why do you need both?

Key points

/rewind is a local rollback within a single Claude Code session. It stores incremental snapshots for up to 30 days, up to 100 per session. git is long-term project history, shared across the team, with branches, merge conflicts, and a remote repository. One doesn't replace the other. The best practice is to make a git commit at each logical milestone and rely on /rewind between commits.

Anthropic's documentation states this pairing directly:

Checkpoints are designed for fast session-level recovery. For commits, branches, and long-term history, continue using a version control system (for example, Git). Checkpoints complement, but do not replace, normal version control. Think of checkpoints as 'local undo' and Git as 'permanent history'.

— Anthropic Docs, https://code.claude.com/docs/en/checkpointing

The differences in one table:

Parameter/rewindgit
GranularityEvery turn in the conversationEvery commit
StorageUp to 30 days, up to 100 per session, locally in ~/.claude/file-history/Permanently, in the repository's .git/ and on the remote server
What it tracksClaude's edits through its own toolsAll committed changes
What it does NOT trackBash, external edits, migrations, pushUncommitted changes
CommandA command within ClaudeAn external version control system
Rewinds conversationYesNo
Works across sessionsOnly within the same sessionEverywhere

The pairing is simple: whenever you reach a state where “this is working, and I don't want to lose it,” make a git commit. Between commits, rely on /rewind—it's instant, doesn't require a commit message, and doesn't clutter git history with intermediate states. When the work is done, commit—preferably a meaningful, atomic one.

Why doesn't one /rewind cover the whole task?

Undo is one case of context engineering. Manage session context (when to commit, when to press /rewind, what rules to put in CLAUDE.md) and you get a predictable Claude that doesn't destroy the project or lose work.

Why is git reset --hard dangerous when you ask Claude to “roll back”?

Key points

In natural language, “roll back” means “look at the history,” not “destroy it”; Claude should offer git checkout by default, not reset --hard; protection is configured in CLAUDE.md.

A request to “save the current state and roll back to the last push” can lead to these commands:

git stash save "WIP: Tracker enter/leave disabled + fsSyncModule fix"  # saved uncommitted changes
git reset --hard 35eb731                                                # destroyed commits d63695e..882e618

The first command was correct—it saved the uncommitted changes in the stash. The second was destructive: it rewrote the branch to commit 35eb731, and all commits between it and 882e618 became orphaned. By default, orphaned commits remain in .git/objects/ until git gc runs, which usually happens automatically within two weeks. But if you didn't know what to do at that moment, time was already working against you.

The logic is simple: in natural language, “roll back,” “go back,” “restore,” “revert,” and “undo” mean “look back” or “return to a safe place.” They don't mean “destroy history.” The git reset --hard command destroys it—it rewrites the branch and removes commits from those reachable through HEAD. A safe alternative is git checkout <commit>, which creates a detached HEAD and lets you view the old state without touching branches.

The main practical takeaway is to git commit the current state before any substantial task, especially before refactoring multiple files. One commit turns any Claude screw-up into one git checkout . command without losing work.

How does git reflog save you after a destructive reset?

Key points

git reflog shows the local history of all HEAD movements in the repository—even commits removed through git reset --hard or force-push. Each movement is stored for 90 days by default. If Claude (or you, or someone else) destroyed commits with a destructive command, git reflog will show their hashes, and you can restore the branch with git reset --hard <reflog-hash>.

After a destructive reset, run git reflog right away:

git reflog

The output looks like this:

35eb731 HEAD@{0}: reset: moving to 35eb731
882e618 HEAD@{1}: commit: middleware refactoring complete
d63695e HEAD@{2}: commit: leaveRemove method finalized
1f9c8a3 HEAD@{3}: commit: tracker enter/leave disabled
35eb731 HEAD@{4}: pull origin main

HEAD@{1} through HEAD@{3} are those very “destroyed” commits. They haven't disappeared from git's local object store; they've simply become inaccessible through the branch. To restore them:

# Create a branch from the last “destroyed” commit
git branch recovered-work 882e618

# Or switch directly
git reset --hard 882e618

After that, the branch once again contains all the history up to the disaster.

Reflog limitations:

  1. Local only. The reflog is stored in .git/logs/HEAD; it isn't on the remote repository. If you force-push and then delete your local repo copy, the reflog goes with the folder.
  2. 90 days by default. Older entries may be removed by git gc. You can configure it with git config gc.reflogExpire 200.days.ago.
  3. Doesn't cover what was never in HEAD. If a commit was only in the stash and the stash was destroyed, the reflog will show only the stash's latest state, not its internal history.

Rule for the team: never run git gc --aggressive right after a disaster. First investigate with reflog and recover; do everything else afterward. And never delete the local repository clone until you're sure everything you need has been pushed.

How do you protect a project from destructive git commands through CLAUDE.md?

Key points

In your project's CLAUDE.md, add a block of instructions defining which git commands Claude can run by itself, which require explicit confirmation, and which are forbidden without an exact phrase from the user. Claude treats CLAUDE.md as the project's system prompt and follows these rules by default. This turns one “dangerous” prompt into two safe commands.

The vulnerability is that Claude has no protective context by default. It interprets “roll back” as git reset --hard because technically that's a valid method. Put the protection in CLAUDE.md—the project's system prompt file.

Minimal rule (insert into your CLAUDE.md):

## Git Safety Protocol

- NEVER run destructive git commands (push --force, reset --hard, checkout ., restore ., clean -f, branch -D) unless I explicitly request these actions. Taking unauthorized destructive actions is unhelpful and can result in lost work.
- When I say "roll back", "go back", "restore", "revert", "undo" - interpret as REVIEW commands: use `git log`, `git diff`, `git checkout <commit>` (creates detached HEAD), or `git stash` (preserves changes).
- ALWAYS ask for confirmation before ANY command that:
  - Changes HEAD position to a different commit on a branch
  - Modifies commit history
  - Could lose uncommitted work
  - Includes flags --hard, --force, --aggressive
- Before any destructive command, output a numbered comparison:
  - SAFE: use `git checkout <commit>` to view temporarily
  - DESTRUCTIVE: use `git reset --hard` to permanently destroy
- Wait for my explicit choice before executing.

Extended rule for the team (add to the repository root's CLAUDE.md):

## Git Workflow Rules

- Commit at each working milestone. Before a WIP commit, run `git status` and `git diff`, stage only explicitly reviewed named files with `git add -- path/to/file`, then inspect the staged diff before committing. A timer is a reminder to review, not permission to stage the entire working tree.
- Never use `git add .` or `git add -A` for commits by Claude. Only specify files by name, after `git status` + `git diff`.
- Before `git push --force` to main—stop and ask me. In feature branches, force-push cautiously, only if you're sure I'm willing to lose the previous version.
- When resolving merge conflicts, never choose "ours" or "theirs" immediately—show me both versions first, then I'll decide.
- `.gitignore` must contain `.env*`, `.claude/personal/`, `node_modules/`, `dist/`. If they're missing, add them.

After adding these blocks, the next phrase “roll back to the last push” would lead to this response:

I see 3 uncommitted files and 4 commits ahead of the last push. Two options:

  1. SAFE: create a view-last-push branch through git checkout <last-push-hash>—I’ll preserve all the work, but temporarily show the state of the push.
  2. DESTRUCTIVE: git reset --hard <last-push-hash>—I’ll permanently destroy 4 commits and the uncommitted changes. They can be restored only through git reflog within 90 days. Which do you choose?

That’s half a minute of conversation instead of four hours of lost work.

What are the 5 ways to undo in Claude Code, and how do you choose the right one?

Key points

If something goes wrong, there are five levels of desperation: /rewind (within a session), git checkout . (uncommitted changes), git checkout <commit> (return to an old commit without losing history), git reset --hard <commit> (move the branch back, losing commits ahead of it), git reflog + recovery (disaster, everything is gone). Each level is heavier and more dangerous than the previous one.

The scenario “Claude broke it, I need to restore it urgently” proceeds from the bottom up this ladder. Always start at level 1.

Level 1. /rewind—instant undo within a session.

Press Esc Esc or type /rewind. Choose the point before the break. Choose a mode (usually Restore code and conversation). A second later, you're back in the past and can start over. Covers 80% of “Claude did the wrong thing” cases.

Level 2. git checkout .—undo all uncommitted changes.

git diff                    # first see what actually changed
git checkout .              # undo all uncommitted changes in all files
# or selectively:
git checkout -- path/to/file.ts   # only one file

Useful when /rewind didn't work (for example, Claude touched files through bash) or when you need to undo outside the session history. All changes that weren't committed will disappear permanently. If you might regret that, run git stash first (see level 2.5).

Level 2.5. git stash—put your changes on the shelf.

git stash save "might still need this"
# return to a clean state (without changes)
# ...
# if you change your mind—restore from stash:
git stash pop

A good compromise between “lose forever” and “leave as is.” The stash remains local until explicitly cleared.

Level 3. git checkout <commit>—return to an old commit without losing history.

git log --oneline               # find the hash of the right commit, e.g. abc1234
git checkout abc1234            # detached HEAD—view without changing anything
# like the state? create a branch from it:
git checkout -b recovery abc1234
# return:
git checkout main

This is a safe “temporary return.” Detached HEAD doesn't change the branch; your current work in main (or whichever branch you were on) remains intact. If you want to work with this state, create a branch.

Level 4. git reset --hard <commit>—move the branch back to a point.

⚠️ Destructive. Commits ahead of the specified hash become orphaned.

git reflog                                  # note the hash of the current state
git reset --hard abc1234                    # rewrite the branch
# found a mistake? return through reflog:
git reset --hard HEAD@{1}                   # to where you were before the reset

Use only if you're sure you don't need the commits ahead. And always check git reflog BEFORE reset so you know where to return if you change your mind.

Level 5. git reflog + recovery—a catastrophic scenario.

Someone (Claude, you, a colleague) has already run git reset --hard or force-push and wiped out the work. What do you do?

git reflog                                          # look for the last hash before the disaster
git branch recovered HEAD@{N}                       # create a branch from it
git checkout recovered                              # switch to it
git diff main                                       # compare with the current state
git checkout main && git merge recovered            # restore into main, if you're sure

If the reflog has already been cleared (after 90 days by default), the last resort is git fsck --lost-found, which will show dangling commits in .git/objects/. This is nearly archeology, but sometimes it works.

Rule for choosing a level:

What happenedLevel
Claude rewrote 3 files the wrong way1. /rewind
I tried it, didn't like it, the session isn't helping2. git checkout .
I broke it manually, hate to lose it, might restore it2.5. git stash
I committed; need to go back one commit3. git checkout <commit>
I'm sure I don't need the commits ahead4. git reset --hard
Already wiped it with a destructive command5. git reflog

How do you protect a project so there's nothing to undo?

Key points

The best undo is the one you don't need. Three protection rules: review progress every 30 minutes and commit a working milestone by explicitly staging only reviewed paths; put the required .claude/personal/ and .env* lines in .gitignore; do major experiments in a separate branch with git checkout -b experiment-<name>. This narrows the recovery gap for committed files; external systems and uncommitted work still need their own recovery plan.

Rule 1. Commit every 30 minutes.

Don't wait until “the task is done.” Commit any intermediate step that works. Commit messages can be anything; the main thing is that Claude (or you) can return to a working state with one git checkout command.

# at the beginning of a task
git status                        # inspect all staged and unstaged paths
git diff                          # review the changes
# Replace this example path with the actual file you reviewed.
git add -- path/to/file.ts
git diff --cached                 # verify exactly what will be committed
git commit -m "wip: starting User schema migration"

# after 30 minutes (or after the first working iteration)
git status
git diff
git add -- path/to/file.ts         # actual reviewed path, not a directory wildcard
git diff --cached
git commit -m "wip: User schema is ready, migration applied locally"

# at the end of the task—a meaningful commit
git reset --soft HEAD~2           # combine the three wip commits into one
git commit -m "feat(auth): add lastLoginAt field to User table"

If you add a PostToolUse reminder, keep the same review and explicit-path staging rule. Do not turn a timer into an unchecked auto-commit: unrelated edits or already staged files can otherwise enter the commit.

Rule 2. Minimum .gitignore.

These lines are required in the project root:

# secrets
.env
.env.local
.env.*.local

# local Claude Code settings (not pushed to the team repository)
.claude/personal/
.claude/sessions/
.claude/file-history/

# dependencies and build
node_modules/
dist/
.next/
build/

I keep the .claude/personal/ folder for my own experiments and notes, which must not be included in the shared repository. The .claude/sessions/ and .claude/file-history/ folders are Claude Code's local storage; they don't belong in the repository, take up a lot of space, and are tied to a specific machine.

Rule 3. Experiments on a separate branch.

If the task is large (refactoring 10+ files, migrating to a new database, rewriting a module), don't do it on the main branch:

git checkout -b experiment/auth-rewrite
# work, commit every 30 minutes
# if it works:
git checkout main
git merge experiment/auth-rewrite
# if it doesn't:
git checkout main
git branch -D experiment/auth-rewrite     # delete the branch
# that's it, the main branch is intact

This simple habit turns “Claude trashed the project” into “Claude trashed one branch, I deleted it, and we start over.”

Rule 4. Before dangerous operations, use git tag.

Before a database migration, a large refactor, or a dependency update, create a tag:

git tag pre-prisma-migration-v2
# work
# something went wrong:
git reset --hard pre-prisma-migration-v2
# or just take a look:
git checkout pre-prisma-migration-v2

A tag is a named pointer to a commit that you won't lose even through reflog cleanup.

What's next: how does undo fit into context engineering?

Key points

Undo isn't a separate skill but part of managing Claude Code session context. When you know when to press /rewind, when to git commit, and when to git stash, you're managing a whole workflow, not one command. This is part of Context Engineering. Without it, Claude acts like an ordinary assistant; with it, like a predictable tool.

These three levels of undo are the infrastructure for one skill: knowing how to restore a state when it breaks. That skill is narrow by itself. But combined with other context engineering tools, it becomes something more.

Plan Mode doesn't let you write code immediately—first comes the plan, then confirmation, then execution. This is preventive undo: you don't write what you'll later have to undo because the plan was reviewed in advance. Read more in the guide to Plan Mode in Claude Code.

CLAUDE.md sets rules that Claude respects by default, including the Git Safety Protocol we covered above. This is preventive protection against destructive commands.

The Second Brain gives Claude memory about the project between sessions—it knows what code you have, what the business logic is, and what agreements were made earlier. The more memory, the less likely it is to do the wrong thing.

Skills and subagents are your methodology in code. If the correct git workflow is built into a Skill, no subagent will run git reset --hard without confirmation.

And all of this together is Context Engineering. Manage context before the prompt, not during it. Read more in what is context engineering.

Undo is the last line of defense. Plan Mode + CLAUDE.md + Second Brain + Skills are the first four. When they are set up, undo becomes rare and quick. When they're not, it becomes a daily ritual.

Undo begins where planning ends.

Open Ailoot.

More details

Questions about How to undo changes in Claude Code: /rewind and git

Should a WIP checkpoint use git add .?

No. Run git status and git diff, stage only the named files you reviewed, then inspect git diff --cached before committing. A periodic checkpoint does not authorize including unrelated or previously staged changes.

Can /rewind undo a database migration or remote API action?

No. The guide limits checkpoints to supported file edits in the session. Database, remote Git, and API effects need separate recovery steps; use Git or a backup for files outside the checkpoint’s coverage.

All articles