Recovery with Reset, Stash, and Reflog
What This Concept Is
First identify what needs recovery: committed history, staged content, unstaged tracked edits, or untracked/ignored files. A branch name preserves a commit, not all current files. Reflogs record local reference movements and can expire; they are not a permanent backup of unsaved or never-recorded work.
Why It Matters Here
Recovering the wrong layer can turn a small mistake into lost work. A committed tip, an unfinished edit and an untracked note need different evidence and recovery choices. Practice those distinctions before using recovery in a real project.
How To Use It
- Unstage:
git restore --staged fileleaves the working file intact when HEAD exists. - Redo a private commit:
git reset --soft HEAD~1moves the current branch back while retaining index and working-tree contents. Inspect before recommitting. - Reverse a shared change:
git revertadds a new inverse commit; verify behavior and any conflict resolution. - Shelve tracked changes: ordinary
git stash pushsaves tracked staged/unstaged work. Use-udeliberately for untracked files; ignored files still remain outside it. - Recover a committed tip: inspect
git reflog, inspect the chosen commit ID withgit show, then create a named branch there. Do not assumeHEAD@{1}is always the commit you want.
Common Confusion / Misconception
reset --hard can discard tracked changes and may remove obstructing untracked files. It is not the default recovery step. Creating a branch alone does not protect unfinished changes; inspect and preserve those separately before any destructive operation.
Concrete Example
1. Reflog drill without discarding files
Start clean on main in the disposable guided-lab repository. Use a fresh branch:
git switch -c recovery-practice
printf 'Keep this committed evidence\n' > recovery.txt
git add recovery.txt
git commit -m 'Record recoverable evidence'
git rev-parse HEAD
git reset --soft HEAD~1
git status --short
git reflog -5
Write down the evidence commit ID before reset. After reset, the change remains staged. Inspect the reflog to identify that commit; do not guess based only on position. In the next commands replace COMMIT_ID with the actual ID you inspected—do not type the placeholder literally:
git show COMMIT_ID:recovery.txt
git branch recovered-evidence COMMIT_ID
git switch recovered-evidence
git status --short
cat recovery.txt
The recovered branch names the original commit, and the staged snapshot already matches it, so the switch should leave clean state. This recovers the original commit without creating a duplicate. Explain why soft reset preserved the index and why reflog cannot promise recovery of an untracked file that was never stored.
Mini Drill or Application
2. Shelve and restore tracked plus untracked work
On the clean recovered branch:
printf 'An unfinished tracked edit\n' >> recovery.txt
printf 'An untracked note\n' > draft.txt
git status --short
git stash push -u -m 'Practice pause with untracked note'
git status --short
git stash list
git stash show --stat 'stash@{0}'
git stash apply 'stash@{0}'
cat recovery.txt
cat draft.txt
git stash list
The default stash summary shows tracked changes; verify the untracked note by inspecting it after restoration. The tracked edit and untracked note return; apply retains the stash entry. It does not promise restoration of the exact staged/unstaged split; --index attempts that and can fail. In this controlled fixture there are no newer edits, so application should be conflict-free. Do not drop the stash before verifying both files. Once verified, preserve the recovered work in a commit:
git add recovery.txt draft.txt
git commit -m 'Preserve recovered unfinished work'
git stash drop 'stash@{0}'
git status --short
For fresh transfer, create a new tracked edit and an untracked file and predict what ordinary stash (without -u) leaves behind. Verify, then restore using apply and preserve both files before dropping the exercise stash. Explain how an ignored file differs. Never use stash -a or cleanup commands on personal files just to satisfy this exercise.
Check Yourself
Can you name which layer each command changed, what was preserved, and what would remain unrecoverable?
Acceptance and repair
Keep the before/after branch IDs, three-state explanations, chosen reflog entry, recovered content, stash inclusion prediction and observed restoration. A command that exits successfully without the intended content is insufficient. If stash application conflicts, preserve the entry and diagnose from status; do not blindly pop, drop or hard-reset. Use a smaller fresh fixture to repair the model.
Sources: official reset, stash and reflog documentation. These describe tool behavior, not evidence that this exercise establishes beginner mastery.
Read This Only If Stuck
Use the Recovery and Safe Undo source map for selective reading, or the Pro Git overview for the book map. Book-overview links are thematic guides, not exact chapter extracts.