Restore, revert, and reset at a glance
Git documentation groups the three commands under the heading Reset, restore and revert. Each targets a different layer of the repository. Restore updates files in the working tree or the index from a specified source. Revert creates a new commit whose patch is the inverse of an existing commit. Reset changes which commit the current branch points to and optionally updates the index and working tree. Because the commands operate at different layers, they produce different results when history is involved.
The working tree holds the files you edit. The index holds the next commit snapshot. HEAD points to the current commit on the active branch. Restore touches the working tree or index without moving HEAD. Revert adds a commit without moving HEAD. Reset can move HEAD and rewrite the index or working tree in one step.
- git restore updates files or the index from another commit or the index itself
- git revert records an inverse commit and leaves existing history intact
- git reset moves the branch pointer and can discard commits from the current branch
When to reach for git restore
Restore is the right tool when you want to bring a file back to a previous version without touching commit history. You can restore a single file from HEAD or from any other commit. The command does not create or remove commits, so it is safe on any branch. It also updates the index when you use the --staged flag, letting you unstage changes without discarding them from the working tree.
A common pattern is restoring a file that was accidentally edited or deleted. Because restore only affects the working tree or index, teammates who have already pulled the branch will not see any change in history. The command therefore carries low risk when used for local cleanup.
- git restore --source=HEAD~1 path/to/file restores one file from the previous commit
- git restore --staged path/to/file unstages changes while keeping them in the working tree
- Restore never moves HEAD or rewrites published commits
When to reach for git revert
Revert is the preferred command for undoing a published commit. It calculates the changes introduced by the target commit and records a new commit that applies the opposite patch. The original commit remains in history, so anyone who has already fetched the branch can still pull the new revert commit without conflict. Git documentation explicitly recommends revert for shared history because it avoids the force-push problems that reset can create.
You can revert a single commit or a range of commits. The resulting history shows both the original change and the reversal, which helps future readers understand what happened. Revert requires a clean working tree before it starts, so staged or modified files must be committed or stashed first.
- git revert HEAD~1 creates a new commit that undoes the most recent commit
- git revert --no-commit lets you review the inverse changes before committing
- Revert works on any branch and never requires a force push
When to reach for git reset
Reset moves the current branch pointer to a different commit. The --soft, --mixed, and --hard options control how much of the working tree and index are updated. Because reset can remove commits from the branch history, it is only safe on branches that have never been pushed or shared. Once a commit has been fetched by another developer, resetting past that commit will cause push failures and potential data loss for teammates.
The --hard option is the most destructive because it overwrites both the index and the working tree. The --soft option leaves the working tree and index unchanged, which is useful for combining several local commits into one. Even on private branches, a hard reset should be used with care because it discards uncommitted changes that have not been saved elsewhere.
- git reset --soft HEAD~3 moves HEAD back three commits but keeps changes staged
- git reset --hard HEAD~1 discards the last commit and any uncommitted changes
- Reset should never be used on a branch that has already been pushed to a shared remote
Practical decision checklist
Before running any undo command, ask three questions: Has the commit been pushed? Do I need to keep the commit in history? Do I only need to change files or the index? If the commit is public, choose revert. If the branch is private and you want to discard commits, choose reset. If you only need to restore a file or unstage changes, choose restore. The checklist prevents most accidental rewrites of shared history.
After any undo operation, run git status and git log to confirm the result. When working on a team, communicate the change so others know whether to pull a revert commit or rebase their own work. Keeping these steps consistent reduces the chance of force-push conflicts later.
- Check git status before and after every undo command
- Prefer revert on any branch listed in git branch -r
- Document the reason for the undo in the commit message when using revert