Undo & Recovery Workshop
Practice recovering from common Git mistakes. Each exercise simulates a real scenario you might encounter.
Setup
Create a repository with some history:
bash1$ mkdir undo-practice && cd undo-practice2$ git init34$ echo "Line 1" > file.txt5$ git add file.txt6$ git commit -m "first commit"78$ echo "Line 2" >> file.txt9$ git add file.txt10$ git commit -m "second commit"1112$ echo "Line 3" >> file.txt13$ git add file.txt14$ git commit -m "third commit"
Check the history:
bash1$ git log --oneline2abc1234 third commit3def5678 second commit4ghi9012 first commit
Exercise 1: Unstage a File
Scenario
You accidentally staged a file you didn't mean to include.
bash1$ echo "debug info" > debug.log2$ git add debug.log3$ git status4Changes to be committed:5 new file: debug.log
Solution
bash1$ git restore --staged debug.log23$ git status4Untracked files:5 debug.log
The file is unstaged but still exists.
Verify
bash1$ cat debug.log2debug info
Exercise 2: Discard Local Edits
Scenario
You made changes to a file but want to revert to the committed version.
bash1$ echo "BAD CHANGE" > file.txt2$ cat file.txt3BAD CHANGE45$ git status6Changes not staged for commit:7 modified: file.txt
Solution
bash1$ git restore file.txt23$ cat file.txt4Line 15Line 26Line 3
The file is restored to its committed state.
Exercise 3: Undo Last Commit (Keep Changes)
Scenario
You committed too early and want to add more to the commit.
bash1$ echo "Line 4" >> file.txt2$ git add file.txt3$ git commit -m "incomplete commit"45$ git log --oneline6xyz0001 incomplete commit7abc1234 third commit8...
Solution
bash1$ git reset --soft HEAD~123$ git status4Changes to be committed:5 modified: file.txt67$ git log --oneline8abc1234 third commit9def5678 second commit10ghi9012 first commit
The commit is undone, but changes are still staged.
Complete the Exercise
bash1$ echo "Line 5" >> file.txt2$ git add file.txt3$ git commit -m "complete commit with lines 4 and 5"
Exercise 4: Undo Last Commit (Unstage Changes)
Scenario
You want to undo a commit and reorganize what goes in it.
bash1$ git log --oneline2xyz0002 complete commit with lines 4 and 53abc1234 third commit4...
Solution
bash1$ git reset HEAD~123$ git status4Changes not staged for commit:5 modified: file.txt
Changes are in the working tree but unstaged.
Recommit
bash1$ git add file.txt2$ git commit -m "properly organized commit"
Exercise 5: Hard Reset to Remote
Scenario
Your local main has diverged and you want to match origin exactly.
First, simulate divergence:
bash1$ echo "Local only change" >> local.txt2$ git add local.txt3$ git commit -m "local commit that should not exist"
Solution
Since we don't have a real remote, simulate with a tag:
bash1# Mark the "good" state2$ git tag good-state HEAD~134# Reset to it (simulating reset to origin/main)5$ git reset --hard good-state67$ git log --oneline8# The "local commit" is gone
In real usage:
bash1$ git reset --hard origin/main
Exercise 6: Revert a Deployed Bug
Scenario
A commit introduced a bug, but it's already pushed and deployed.
bash1$ echo "BUGGY CODE" >> file.txt2$ git add file.txt3$ git commit -m "feat: introduce bug"45$ git log --oneline6bug1234 feat: introduce bug7...
Solution
bash1$ git revert HEAD2# Editor opens for commit message3# Save and close45$ git log --oneline6rev5678 Revert "feat: introduce bug"7bug1234 feat: introduce bug8...910$ cat file.txt11# BUGGY CODE line is removed
The bug is undone with a new commit, preserving history.
Exercise 7: Find Lost Work with Reflog
Scenario
You accidentally reset and lost commits.
bash1# Create a commit2$ echo "Important work" >> important.txt3$ git add important.txt4$ git commit -m "important work"56# Accidentally lose it7$ git reset --hard HEAD~189$ git log --oneline10# "important work" commit is gone!
Solution
bash1$ git reflog2abc1234 HEAD@{0}: reset: moving to HEAD~13imp5678 HEAD@{1}: commit: important work4...56# Recover the commit7$ git reset --hard imp567889$ git log --oneline10imp5678 important work11...1213$ cat important.txt14Important work
The lost work is recovered!
Exercise 8: Recover a Deleted Branch
Scenario
You deleted a branch before merging.
bash1# Create and commit on a branch2$ git checkout -b feature/oops3$ echo "Feature code" > feature.txt4$ git add feature.txt5$ git commit -m "add feature"67# Switch and delete8$ git checkout main9$ git branch -D feature/oops10Deleted branch feature/oops (was feat123).
Solution
bash1$ git reflog2abc1234 HEAD@{0}: checkout: moving from feature/oops to main3feat123 HEAD@{1}: commit: add feature4...56# Recreate the branch7$ git branch feature/recovered feat12389$ git checkout feature/recovered10$ cat feature.txt11Feature code
Branch recovered!
Cleanup
bash1$ cd ..2$ rm -rf undo-practice
Checklist
- Unstaged a file with
git restore --staged - Discarded local edits with
git restore - Used soft reset to undo a commit but keep changes staged
- Used mixed reset to undo a commit and unstage changes
- Used hard reset to completely discard changes
- Reverted a commit to preserve history
- Used reflog to recover a lost commit
- Used reflog to recover a deleted branch
Summary Table
| Scenario | Command |
|---|---|
| Unstage file | git restore --staged file |
| Discard edits | git restore file |
| Undo commit, keep staged | git reset --soft HEAD~1 |
| Undo commit, keep unstaged | git reset HEAD~1 |
| Undo commit, discard all | git reset --hard HEAD~1 |
| Undo pushed commit | git revert SHA |
| Find lost work | git reflog |
Key Takeaway
Every Git mistake is recoverable if you know the right command. Always check git reflog before giving up on lost work—Git rarely forgets.