What is the difference between git reset and git revert?
git revert makes a new commit that undoes an earlier commit, so history is kept and it is safe on shared branches. git reset moves your branch pointer back to an older commit and removes the later commits from the branch; --soft keeps the changes staged, --mixed keeps them unstaged, and --hard throws them away. Use reset only on local, unpushed work.
Explain it simply
Both are ways to undo. The difference is how.
git revertis like writing a correction in a register. The wrong entry stays, and a new entry below it cancels it. Anyone reading the register sees both.git resetis like tearing pages out of your own rough notebook. The later pages are gone from the branch, as if they never happened.
Because tearing pages out of a shared register confuses everyone else who has a copy, use revert for anything already pushed, and reset only for your own local commits.
Example
Your history:
git log --onelinec3d4e5f (HEAD -> main) Add discount banner
b2c3d4e Fix login validation
a1b2c3d Add login pageRevert the banner commit, which is already on GitHub:
git revert c3d4e5f[main 9f8e7d6] Revert "Add discount banner"
1 file changed, 3 deletions(-)Now there are four commits. The fourth undoes the third. Push it normally.
Reset if the banner commit was only on your laptop:
git reset --soft HEAD~1 # undo the commit, keep changes staged
git reset HEAD~1 # same as --mixed: keep changes, unstaged
git reset --hard HEAD~1 # undo the commit and delete the changesHow it works
git reset <commit> moves the current branch to <commit>. The three modes decide what happens to your files:
| Mode | Branch pointer | Staging area (index) | Working files |
|---|---|---|---|
--soft | Moved back | Unchanged (changes stay staged) | Unchanged |
--mixed (default) | Moved back | Reset (changes become unstaged) | Unchanged |
--hard | Moved back | Reset | Reset (changes lost) |
git revert <commit> works out the opposite of that commit's changes and applies them as a brand new commit. It never moves the branch backward, so nobody else's history breaks.
Real-world use
- Production bug from a merged pull request: revert the merge commit and push. It is quick, it is visible in history, and the team can re-apply the fix later.
- "I committed with the wrong message" or "I forgot a file":
git reset --soft HEAD~1, fix, commit again. Or usegit commit --amend. - "I staged a file by mistake":
git reset <file>orgit restore --staged <file>unstages it without touching your edits. - "I want to throw away all my experiments":
git reset --hard(after double-checking).
Common mistakes
- Running
git reset --hardon a pushed branch and then force pushing. Teammates who pulled the old commits now have a broken history. - Using
--hardwhen you meant--softand losing uncommitted work. Uncommitted changes wiped by--hardare usually not recoverable. - Expecting
git revert HEAD~3to undo the last three commits. It undoes only that one commit. To revert a range, usegit revert HEAD~3..HEAD. - Confusing these with
git restore, which discards changes in files, not commits.
What to say in the interview
"git revert creates a new commit that undoes an earlier one, so it is safe for shared branches because history is not rewritten. git reset moves the branch pointer back and removes commits from that branch. With --soft the changes stay staged, with --mixed, which is the default, they stay in my files but unstaged, and with --hard they are discarded. I use reset only on local commits I have not pushed, and revert for anything already on the remote."
Follow-up questions
- How do you revert a merge commit?
- How do you recover a commit after
git reset --hard? - What is the difference between
git resetandgit restore? - What does
git commit --amenddo?
Go deeper
Read these once the basics above feel easy.
Reverting a merge commit needs you to say which parent is the "main line": git revert -m 1 <merge-commit> keeps the first parent (usually main) and undoes what the merged branch brought in. Later, if you merge that same branch again, Git thinks those commits are already in, so you may need to revert the revert first.
Commits removed with git reset --hard are still in the repository for a while. git reflog shows every position HEAD has been in, such as HEAD@{2}: commit: Add discount banner. Run git reset --hard HEAD@{2} or git branch rescue HEAD@{2} to get them back. This only works for committed work; uncommitted edits were never stored by Git.