Part III · Shell and commands
30.2 Undoing things in git
alsogit undogit resetgit revertgit restoregit reflogreflogundo commitgit commit --amendamendlost commitdiscard changesgit stashstashunstage
TL;DR
- Committed work is almost never lost: the reflog remembers every place a branch has been. Uncommitted edits are the fragile part.
- Pick the command by what you want back: a file, a commit, or a commit others already have.
git restore --staged FILE # unstage a file, keep the edits
git restore FILE # drop your edits to it: gone for good
git reset --soft HEAD~1 # undo the last commit, keep its changes
git revert COMMIT # undo a pushed commit with a new commit
git reflog # where HEAD has been: find lost commits
Pitfalls
⚠ git reset --hard,⚠ git restore,⚠ git checkout -- FILEand⚠ git clean -fthrow away uncommitted work: git has no copy of it.- Don't amend or reset commits others already pulled: use
git revert, which undoes by adding a commit. git stashbefore a risky command keeps your edits aside;git stash popbrings them back.git clean -nlists what⚠ git clean -fwould delete.
Deep dive 2 questions
How can the reflog save me?
Every time HEAD moves (commit, reset, rebase, checkout), git writes the
old and new positions in the reflog, for 90 days by default. A commit
"lost" by a bad reset or rebase is still in the object store: find it in
git reflog, then git branch rescue ID or reset to it. Only
uncommitted changes are truly unrecoverable.
reset, restore, revert: which is which?
restore changes files (working tree or staging area) and never moves a
branch. reset moves the current branch to another commit; --soft
keeps your changes staged, the default keeps them unstaged, --hard
discards them. revert creates a new commit that applies the opposite
of an old one, leaving history as it was.