How it works
The explanation, with examples you can run.
restore: throw away or unstage edits
git init -q -b main demo && cd demofor n in 1 2 3; do echo "v$n" > notes.txt; git add notes.txt; git commit -q -m "Notes v$n"; doneecho "oops" > notes.txtgit restore notes.txtcat notes.txtecho "draft" > notes.txt && git add notes.txtgit restore --staged notes.txtgit status --shortv3 M notes.txtgit restore <path> copies the index version over the working tree, so oops is gone for good. --staged copies HEAD's version into the index; the draft edit stays on disk, now unstaged. --source=<commit> restores from any commit instead.
reset: move the branch
git restore notes.txtgit log --onelinegit reset --soft HEAD~1git status --shortgit log --onelinea8c64d8 Notes v3d4cbec6 Notes v246f1e57 Notes v1M notes.txtd4cbec6 Notes v246f1e57 Notes v1--soft moved main back to v2. The v3 content is still in the index and on disk, staged (M in the first column), ready to be committed again, perhaps with a better message. Recommit, then try the other two modes:
git commit -q -m "Notes v3 again"git reset -q HEAD~1git status --shortgit commit -q -am "Notes v3 once more"git reset --hard HEAD~1cat notes.txt M notes.txtHEAD is now at d4cbec6 Notes v2v2| Mode | Branch | Index | Working tree |
|---|---|---|---|
--soft | moved | kept | kept |
--mixed (default) | moved | reset to target | kept |
--hard | moved | reset to target | reset to target |
After --mixed the change is still on disk but unstaged ( M). After --hard both are back at v2. The commits that were dropped are not deleted; the reflog topic shows how to get them back. Uncommitted edits overwritten by --hard cannot be recovered.
revert: undo in public
git revert --no-edit HEAD > /dev/nullgit log --onelinecat notes.txt55df303 Revert "Notes v2"d4cbec6 Notes v246f1e57 Notes v1v1The new commit reverses v2's change and history shows both. Use revert on any branch others have pulled. Reverting a merge needs -m 1 to say which parent's side to keep.
Which one?
- Edited a file and want the committed version back:
git restore <path>. - Staged something by mistake:
git restore --staged <path>. - Last commit not pushed and you want to redo it:
git commit --amend, orgit reset --soft HEAD~1. - Local commits you want to throw away entirely:
git reset --hard <commit>(stash first if anything is uncommitted). - A pushed commit is wrong:
git revert <commit>.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.