Skip to content
SDETRole
SDETRole

Git interview question

How do you undo a commit? Compare git reset, git revert and git restore.

intermediate 2–5 yrs #reset#revert#restore#reflog#undo

Short answer

git revert creates a new commit that undoes an earlier one, so it is safe on shared branches. git reset moves the branch pointer back, with --soft, --mixed or --hard deciding what happens to staged and working changes; use it only on unpushed commits. git restore discards file changes. git reflog recovers mistakes.

Answer

The right tool depends on whether the commit has been shared. If it has been pushed to a branch others use, I use git revert, which adds a new commit that undoes the change and leaves history intact. If the commit is only local, git reset can move the branch back as if the commit never happened. For uncommitted file changes, git restore is the modern command. And if I get it wrong, git reflog almost always lets me recover.

git revert: undo by adding a commit

git revert a1b2c3d            # creates "Revert '<message>'" commit
git revert --no-edit HEAD     # undo the latest commit
git revert -m 1 <merge-sha>   # revert a merge commit, keeping parent 1 (usually main)

Nothing is rewritten, so everyone can pull it normally. It is the correct way to back out a bad change on main, for example a test change that broke the pipeline.

A subtlety with merges: after reverting a merge, re-merging the same branch later will not bring those changes back, because Git considers them already merged. You must revert the revert.

git reset: move the branch pointer

git reset --soft  HEAD~1   # undo commit; changes stay STAGED
git reset --mixed HEAD~1   # (default) undo commit; changes stay in working tree, unstaged
git reset --hard  HEAD~1   # undo commit AND discard the changes
Mode Branch pointer Staging area (index) Working files
--soft moved kept kept
--mixed moved reset kept
--hard moved reset reset (changes lost)

Typical uses:

  • --soft HEAD~3 to squash the last three local commits into one.
  • --mixed to unstage everything and re-split changes into better commits.
  • --hard origin/main to throw away local experiments and match the remote.

Resetting commits that were already pushed requires a force push and causes the same problems as rebasing shared history. Do not do it on shared branches.

git reset --hard also discards uncommitted work, which reflog cannot recover because it was never committed. Run git status or git stash first.

git restore: file-level undo (Git 2.23+)

git restore path/to/file.ts              # discard unstaged changes in that file
git restore --staged path/to/file.ts     # unstage, keep the changes
git restore --source=HEAD~2 path/to/file # bring back the file as it was two commits ago

These replace the overloaded git checkout -- file and git reset HEAD file forms, which still work.

git reflog: the safety net

Every move of HEAD is recorded locally:

git reflog
# 9f8e7d6 HEAD@{0}: reset: moving to HEAD~1
# a1b2c3d HEAD@{1}: commit: Add checkout tests
git reset --hard a1b2c3d     # or: git branch rescue a1b2c3d

Reflog entries expire (by default after 90 days for reachable entries and 30 days for unreachable ones), and they are local to your clone.

Quick decision guide

  • Pushed and shared: git revert.
  • Local, want to keep the changes: git reset --soft or --mixed.
  • Local, want to discard: git reset --hard (check for uncommitted work first).
  • Just a file: git restore.
  • Made a mistake: git reflog.

What interviewers look for

  • The shared versus local distinction driving the choice.
  • Correct semantics of --soft, --mixed and --hard.
  • Awareness of git restore and git reflog.
  • Bonus: reverting merges and the “revert the revert” subtlety.

A strong answer covers

  • revert adds a new inverse commit and is safe for pushed history
  • reset moves the branch pointer and rewrites history
  • Explains --soft, --mixed and --hard
  • Uses restore for file-level changes
  • Uses reflog to recover lost commits
Practise answering under time pressure

Type to search across SDETRole.

Full-text search by Pagefind · runs in your browser Open search page →