Undoing changes in Git: reset, revert, restore and stash
Pick the right undo command for each situation, and know which ones are safe after you have pushed.
Screenings often ask how to undo something, because choosing the wrong command can delete work or break a shared branch. The right choice depends on two questions: where is the change now, and has it been pushed?
The three places a change can be
- Working directory: edited files not yet staged.
- Staging area: changes added with
git add, waiting for the next commit. - Commits: saved history, which may also be on the remote after a push.
git status tells you which of these your change is in. Read it before running any undo command.
Undoing uncommitted work
git restore --staged file.pyunstages a file but keeps your edits.git restore file.pythrows away unstaged edits to that file. This cannot be undone.git stashputs all uncommitted changes aside so you can switch branches.git stash listshows what is saved andgit stash popbrings the latest back.
Undoing commits: reset versus revert
git reset moves your branch back to an earlier commit. The mode decides what happens to the changes:
git reset --soft HEAD~1 # undo commit, keep changes staged
git reset --mixed HEAD~1 # undo commit, keep changes unstaged (default)
git reset --hard HEAD~1 # undo commit and discard the changes
git revert <hash> works differently. It adds a new commit that reverses an old one, so history only grows. That makes revert the right tool for anything already pushed to a shared branch.
A simple rule works in most cases:
- Not pushed yet: reset is fine, choosing soft or mixed if you want to keep the work.
- Already pushed and others may have pulled: use revert.
- Never force-push over a shared branch to hide a mistake unless the team has agreed to it.
When something seems lost
Commits removed by a reset are usually still recoverable for a while. git reflog lists where HEAD has been, and you can return with git reset --hard to the hash shown there. Uncommitted changes discarded with --hard or restore are not recorded, so they are truly gone.
Checklist before undoing: run git status, decide whether the change is pushed, prefer revert for shared history, and stash anything you are not sure about before using --hard.
More in Cloud and DevOps