Skip to main content

Sign in

Save your progress and access it from any device.

Or with email

Don't have an account?

Privacy policy

Undo changes in Git: the complete guide

Made a mistake? Committed too early? Pushed a bug? Git has a command for every undo scenario. This guide walks you through every option — from unstaging a file to recovering lost commits.

Complete reference

Six Git commands, one for every undo scenario. Follow the decision tree to find the right command, then learn it in detail with terminal examples.

Decision tree: what do you want to undo?

The right Git undo command depends on where your changes are in the Git workflow. Ask yourself three questions: Is it committed? Is it pushed? Is it staged? The answer points you to the right command.

Not staged, not committed

Modified files in working directory

You edited files but haven't run git add yet.

Use git restore or git clean

Staged, not committed

Files added to the staging area

You ran git add but haven't committed yet.

Use git restore --staged

Committed, not pushed

Local commits only

You committed but the changes are still on your machine.

Use git reset

Committed and pushed

Changes shared with the team

The commit is on the remote. Rewriting history would break things.

Use git revert

Need to pause work

Temporarily shelve changes

You want to set aside your current work and come back to it later.

Use git stash

Lost a commit

Recover from a destructive operation

You ran reset --hard or deleted a branch and need to recover.

Use git reflog

Undo uncommitted changes

These commands operate on your working directory — files you have edited but not yet committed. This is the simplest undo scenario: you changed something and want to go back to the last committed version.

git restore — Discard file modifications

git restore <file> resets a file to its last committed state. All uncommitted edits in that file are discarded. Use git restore . to discard all changes across all files at once. This is the modern replacement for git checkout -- <file>.

Warning: this is irreversible. Once you restore a file, the discarded edits are gone — they were never committed, so Git has no record of them.

git clean — Remove untracked files

git restore only works on tracked files. For untracked files (new files that Git doesn't know about), you need git clean. The -n flag does a dry run so you can preview what would be deleted. The -f flag actually removes the files, and -d includes directories.

Always run git clean -n first. Like git restore, this command is irreversible for untracked files — they were never committed.

Undo staged changes

You ran git add and now a file is in the staging area, ready to be committed. But you changed your mind — you want to unstage it without losing your edits.

git restore --staged — Unstage without losing edits

git restore --staged <file> moves a file out of the staging area and back to the "modified but not staged" state. Your actual edits in the file are preserved — only the staging is undone. This is the modern replacement for git reset HEAD <file>.

You can also combine both flags: git restore --staged --worktree <file> unstages the file and discards the modifications in one go.

Undo local commits

You committed but haven't pushed yet. Since the commit only exists on your machine, you can safely rewrite history without affecting anyone else. The tool for this is git reset.

git reset — Move HEAD backwards

git reset moves the branch pointer (HEAD) to a previous commit. What happens to the files depends on the mode you choose:

  • --soft — Undoes the commit. Changes stay staged (in the index). Use this when you want to amend or split a commit.
  • --mixed (default) — Undoes the commit and the staging. Changes stay in your working directory. Use this to re-select which files to include.
  • --hard — Undoes everything: commit, staging, and working directory changes. Use with extreme caution — this is destructive.

git reset --soft: keep changes staged

git reset --mixed: keep changes unstaged

git reset --hard: discard everything

Undo pushed commits

Once a commit has been pushed, it's shared with the team. Rewriting history with git reset would cause problems for everyone who already pulled. The safe approach is git revert.

git revert — Create a reverse commit

git revert <hash> creates a new commit that does the exact opposite of the specified commit. If the original commit added a line, the revert removes it. If it deleted a file, the revert restores it. The original commit stays in the history — nothing is rewritten.

This is the only safe way to undo a commit on a shared branch. After reverting, you simply push the new commit and your teammates pull it without conflicts.

Save work temporarily

Sometimes you don't want to undo changes — you want to set them aside for a moment. Maybe you need to switch branches for an urgent fix, or you want a clean working directory without losing your progress.

git stash — Shelve changes for later

git stash takes all your uncommitted changes (both staged and unstaged) and saves them on a stack. Your working directory becomes clean. Later, git stash pop restores the most recent stash and removes it from the stack. Use git stash apply instead if you want to keep the stash for reuse.

Useful tip: git stash -u includes untracked files in the stash. And git stash list shows all saved stashes so you can manage multiple work-in-progress contexts.

Recover lost commits

Ran git reset --hard by accident? Deleted a branch? Don't panic. If the commits ever existed, Git still has them — at least for 90 days. The tool to find them is git reflog.

git reflog — Git's safety net

git reflog shows a chronological log of every position HEAD has been at: commits, resets, checkouts, rebases — everything. Even if a commit no longer appears in git log, it will be in the reflog. Find the hash you need and reset or cherry-pick it to recover.

Think of reflog as Git's undo history. It doesn't track file-level changes — it tracks where HEAD pointed at each step. This makes it the ultimate safety net for recovering from nearly any mistake.

That covers every undo scenario in Git. The key takeaway: almost nothing is truly lost in Git. Between restore, reset, revert, stash, and reflog, there is always a way to get back to a good state. Scroll down for a side-by-side comparison of all methods.

Comparison: every Git undo method

A side-by-side breakdown of when to use each command, what it affects, and whether it's safe for shared branches.

CommandActs onRewrites historySafe for shared branchKeeps changesBest for
git restoreWorking directory filesNoYesNo — discards editsDiscarding local file modifications
git cleanUntracked filesNoYesNo — deletes filesRemoving generated or temporary files
git restore --stagedStaging area (index)NoYesYes — keeps edits in working dirUnstaging files before commit
git reset --softCommitsYesNoYes — keeps stagedAmending or squashing local commits
git reset --mixedCommits + stagingYesNoYes — keeps in working dirRe-selecting which files to commit
git reset --hardCommits + staging + filesYesNoNo — discards everythingCompletely discarding local experiments
git revertCommits (creates new one)NoYesYes — original commit staysUndoing pushed commits safely
git stashWorking dir + stagingNoYesYes — saved on stackTemporarily setting aside work
git reflogHEAD history (read-only)NoYesYes — finds lost commitsRecovering from destructive operations
A

GitQuest is created by Anaïs (nouvelle fenêtre), web developer and head of education, specializing in tech training and digital accessibility.

Questions about undoing changes in Git

Master every undo scenario

GitQuest trains you to use restore, reset, revert, stash and reflog in realistic situations. Practice in a safe sandbox — no risk to your real projects.

Start practicing now