Use git restore for local, uncommitted changes, and use git revert for commits that already exist in shared history. That single rule prevents most Git undo disasters. If you are about to erase work only on your machine, restore is usually the right tool. If teammates may already have pulled the commit, revert is the safer move.
TL;DR: git restore changes files back to a chosen state, often HEAD, and is best for cleaning up your working directory. git revert creates a new commit that reverses an older commit, so history stays intact. Example: if a developer changed 12 files and broke checkout locally, git restore . can wipe those edits in seconds; if that bug was already merged to main, git revert abc123 is the safer fix. On a team of 10 developers, reverting a bad public commit can save hours of confused sync problems.
Why this choice matters
Git gives you several ways to undo work, and that is both useful and slightly annoying. Two commands can appear to “undo changes,” yet they affect totally different parts of your project. Pick the wrong one and you may delete local work, rewrite expectations, or confuse everyone who just pulled from the remote.
The safest mental model is simple:
git restorechanges files in your working tree or staging area.git revertadds a new commit that reverses an older commit.restoreis file-focused.revertis commit-focused.
What git restore actually does
git restore was introduced to make undoing file changes clearer than older commands like git checkout -- file. It restores files from another source, usually the latest commit, also known as HEAD.
Use it when you changed a file and regret it before creating a commit:
git restore app.js
That command discards local edits in app.js and returns it to the version in HEAD. It is fast. It is clean. It can also be brutal. If those edits were not saved elsewhere, they are gone.
To discard changes in every tracked file:
git restore .
Honestly, it feels great when you just made a messy experiment and want a clean slate. It feels awful when you run it from the wrong folder and lose 40 minutes of work. Always run git status first.
Unstaging with git restore
git restore can also remove files from the staging area without deleting your edits. This is one of its most useful features.
Suppose you staged too much:
git add .
git status
Then you realize debug.log or a half-finished component got included. To unstage a file, use:
git restore --staged debug.log
The file remains edited in your working directory. It is just no longer staged for the next commit. This is safer than discarding changes, because your work stays on disk.
You can also restore a file from another commit:
git restore --source=HEAD~1 config.yml
That pulls config.yml from one commit back. This is handy when one file needs to go backward while the rest of the branch should stay current.
What git revert actually does
git revert does not erase a commit. Instead, it creates a new commit that applies the opposite changes. The old commit remains in history, which is exactly why it is safe for shared branches.
To revert a commit:
git revert abc123
Git opens your editor with a default commit message, usually something like “Revert…” Save it, and Git records a new commit that undoes the selected one.
This works well when a bug slipped into main, a feature caused production trouble, or a migration broke tests after merge. Since no history is rewritten, your teammates can pull normally.
The key difference: files versus history
| Situation | Best command | Why |
|---|---|---|
| You edited a file but did not commit it | git restore file |
It discards local file changes |
| You staged a file by mistake | git restore --staged file |
It unstages without deleting edits |
| You pushed a bad commit to a shared branch | git revert commit |
It preserves public history |
| You need to undo one old file version | git restore --source=commit file |
It restores only that file |
The catch is that both commands can appear to fix the same problem at first glance. A bug exists. You want it gone. But whether the change is local or committed changes everything.
When git restore is the right choice
Use git restore when your changes have not become part of project history yet. It is best for fast cleanup during development.
- Discarding experiments: You tried a new layout and hate it.
- Cleaning generated files: Your build changed tracked files you do not want.
- Unstaging mistakes: You staged too many files with
git add .. - Restoring one file: You want one file back without touching the branch.
Before running a destructive restore, check what will be affected:
git status
git diff
If the diff contains anything you might want later, commit it to a temporary branch or stash it first:
git stash push -m "save experiment before restore"
When git revert is the right choice
Use git revert when the commit already exists in shared history. This includes commits pushed to main, commits reviewed in a pull request, or commits another developer may have based work on.
Good use cases include:
- Rolling back a broken release: The bad commit is already deployed.
- Undoing a merged feature: The feature was approved but caused issues.
- Keeping an audit trail: The team needs to see what changed and when.
- Avoiding sync pain: Nobody has to repair rewritten history.
To revert several commits without committing each one immediately, use:
git revert --no-commit abc123
git revert --no-commit def456
git commit -m "Revert broken checkout changes"
This produces one clean rollback commit. Expect to spend a few extra seconds checking conflicts, but that is better than making the branch harder to trust.
Common mistakes to avoid
- Using
git restore .too quickly: It can discard all tracked local edits below your current directory. - Reverting the wrong commit: Always confirm with
git log --oneline. - Assuming revert removes history: It does not. It adds a new commit.
- Restoring untracked files:
git restoredoes not remove untracked files. For that, people often usegit clean, which needs extra care.
A practical safety checklist
Before undoing anything, run:
git status
git diff
git log --oneline -5
Then ask three questions:
- Has this change been committed? If no, think
restore. - Has this commit been pushed? If yes, think
revert. - Do I need this work later? If maybe, stash or branch first.
For solo local cleanup, git restore is quick and direct. For shared project history, git revert is the professional option. One edits your working files. The other records a public undo. Knowing that split turns Git from a panic button into a controlled recovery tool.
