😰 Story time: I ran
git reset --hard HEAD~1, force pushed… and then realized I needed that file back.
TL;DR
- Not pushed yet →
reset - Pushed + shared branch →
revert - “Lost” a commit →
git reflog
The real-world scenario
You’re working on a repo and you create commits like:
chore: remove compiled artifacts from the repositorychore: add .gitignore to exclude unnecessary files
Then you try to undo the last commit, you run push --force-with-lease, and later you say:
“I need to recover that file.”
Let’s go step by step.
1) Undo the last commits: reset vs revert
Rule of thumb:
- ✅ Working alone / not pushed yet → use
reset - 👥 Shared branch / already pushed → use
revert
Before you copy/paste commands, get your current branch name:
git branch --show-current
Enter fullscreen mode Exit fullscreen mode
Use that value wherever you see YOUR_BRANCH.
Option A: reset (rewrites history)
Useful when you want those commits to disappear from the history.
- Deletes commits and discards changes (hard mode):
git reset --hard HEAD~2
Enter fullscreen mode Exit fullscreen mode
- Deletes commits but keeps changes staged (soft mode):
git reset --soft HEAD~2
Enter fullscreen mode Exit fullscreen mode
GitHub note (force push): If you already pushed, to make the remote match you must force push.
Avoid --force and use:
git push --force-with-lease origin YOUR_BRANCH
Enter fullscreen mode Exit fullscreen mode
✅ --force-with-lease is safer because it won’t overwrite remote work you don’t have locally.
⚠️ If the branch is protected (common on main/master), GitHub may block force pushes.
Example:
git push --force-with-lease origin master
Enter fullscreen mode Exit fullscreen mode
Option B: revert (does NOT rewrite history)
Recommended when:
- Other people are working on the repo
- The branch is shared
- The branch is protected (e.g.,
main/master)
It creates new commits that undo the changes:
git revert --no-edit HEAD~2..HEAD
git push origin YOUR_BRANCH
Enter fullscreen mode Exit fullscreen mode
2) Recover commits after reset --hard with reflog
If you ran:
git reset --hard HEAD~1
Enter fullscreen mode Exit fullscreen mode
and then regretted it, your lifeline is:
git reflog
Enter fullscreen mode Exit fullscreen mode
Real example output:
dc65430 HEAD@{0}: reset: moving to HEAD~1
3bfb189 HEAD@{1}: commit: chore: add .gitignore to exclude unnecessary files
dc65430 HEAD@{2}: commit: chore: remove compiled artifacts from the repository
Enter fullscreen mode Exit fullscreen mode
You can see the “lost” commit still exists: 3bfb189.
To return to that state:
git reset --hard 3bfb189
Enter fullscreen mode Exit fullscreen mode
If you also want GitHub to match:
git push --force-with-lease origin YOUR_BRANCH
Enter fullscreen mode Exit fullscreen mode
3) Restore a specific file from an earlier commit
Sometimes you don’t want to move the whole branch—only recover one file that existed in a past commit.
Important
This command always requires a path:
git restore --source <COMMIT> -- <FILE_PATH>
Enter fullscreen mode Exit fullscreen mode
Common example: restore .gitignore from 3bfb189:
git restore --source 3bfb189 -- .gitignore
Enter fullscreen mode Exit fullscreen mode
Then save it in history:
git add .gitignore
git commit -m "chore: restore .gitignore"
git push origin YOUR_BRANCH
Enter fullscreen mode Exit fullscreen mode
Don’t know the exact file path?List the files touched by that commit:
git show --name-status --pretty="" 3bfb189
Enter fullscreen mode Exit fullscreen mode
Or list everything that exists in that commit:
git ls-tree -r 3bfb189 --name-only
Enter fullscreen mode Exit fullscreen mode
Once you find the exact path, restore it:
git restore --source 3bfb189 -- real/path/to/file.ext
Enter fullscreen mode Exit fullscreen mode
Restore EVERYTHING from a commit (warning: overwrites)
⚠️ This can overwrite local changes in your working tree:
git restore --source 3bfb189 -- .
Enter fullscreen mode Exit fullscreen mode
4) Change the last commit message
If you have NOT pushed yet
git commit --amend -m "new message"
Enter fullscreen mode Exit fullscreen mode
If you ALREADY pushed to GitHub
git commit --amend -m "new message"
git push --force-with-lease origin YOUR_BRANCH
Enter fullscreen mode Exit fullscreen mode
5) Tips to avoid Git pain (seriously)
- Before doing an aggressive reset, create a “backup branch”:
git branch backup-before-reset
Enter fullscreen mode Exit fullscreen mode
- Prefer
--force-with-leaseover--force - If you’re working with a team, prefer
revertoverreset -
reflogis your “secret history”: when something “disappears”, checkgit reflog
Wrap-up
If you ever feel like you “lost” commits or files, remember:
-
git reflogfinds the commit you can’t see anymore -
git restore --sourcerestores specific files without breaking everything -
resetrewrites history (requires force push) -
revertis team-friendly
Your turn 👻
What’s your worst Git mistake? Did you manage to recover it, or did you have to start over? Drop your story in the comments.
답글 남기기