Soft, Mixed, and Hard Reset
Soft, Mixed, and Hard Reset
After this page you can predict git status after --soft, --mixed, and --hard, and you can put the branch name back with ORIG_HEAD.
One commit, three trees
Start from a clean main on ~/desk/desk-api (chapter 3). This page adds one scratch commit, tries each mode, and removes that commit at the end.
cd ~/desk/desk-api
git switch main
git statusIgnored files such as .env are fine. Commit or restore any other uncommitted work before you continue.
echo "scratch" >> README.md
git add README.md
git commit -m "lab: reset modes" A ← B ← S main
HEAD, index, and worktree all name S
S is the scratch commit. Each mode below starts from S. Git records the old tip in ORIG_HEAD whenever a reset moves the branch, so git reset --hard ORIG_HEAD returns to S.
--soft moves the name
git reset --soft HEAD~1
git status HEAD → B
index still S "Changes to be committed"
worktree still S
main now names B. The scratch line is staged. git log no longer shows lab: reset modes. The commit object stays in the reflog (chapter 17).
git reset --hard ORIG_HEAD
git log --oneline -1You are back on the scratch commit. The line is in README.md, and status is clean.
--mixed moves the name and the index
--mixed is the default. git reset HEAD~1 and git reset --mixed HEAD~1 are the same command.
git reset HEAD~1
git status
git diffGit prints Unstaged changes after reset:.
HEAD → B
index matches B the scratch line is not staged
worktree still S "Changes not staged for commit"
The patch is in the working tree. The next commit includes it only after git add.
git reset --hard ORIG_HEAD--hard moves all three
git reset --hard HEAD~1
git status
grep scratch README.md || echo "scratch line is gone" HEAD, index, and worktree all match B
tracked files match B
The line is gone from disk. Untracked files are still on disk. --hard rewrites tracked files to the commit you named and leaves untracked and ignored files alone.
git reset --hard ORIG_HEADThe scratch commit is the branch tip again, and the line is back. ORIG_HEAD is the immediate undo. After other commands have moved HEAD, the reflog is the record (chapter 17). The lab at the end of this chapter recovers with HEAD@{1} on purpose.
Remove the scratch commit
git reset --hard HEAD~1
git status
git log --oneline -5lab: reset modes is off the log. README.md has no scratch line. The object remains in the reflog until it expires.
Where this is safe
Use these modes on a local branch nobody else has fetched. On a main other people already have, moving the name and pushing is a force-push (chapter 11). A published undo is git revert (chapter 10). The next page is how to choose restore, reset, or revert.