Recovering from Mistakes: reflog, cherry-pick and More
Rescue “lost” commits with git reflog, recover deleted branches, copy commits between branches with git cherry-pick, find bugs with git bisect, and build habits that prevent disasters.
On this page 11 sections
Introduction
Sooner or later you will run a command and think “I have just lost my work”. A hard reset to the wrong commit, a branch deleted with -D, a rebase gone wrong. The good news: once something has been committed, Git almost never truly deletes it straight away. This lesson shows how to get it back.
- How git reflog records everywhere HEAD has been.
- How to undo a hard reset and restore a deleted branch.
- How to copy a single commit to another branch with git cherry-pick.
- How git bisect finds the commit that introduced a bug.
The Reflog: Git’s Safety Net
The reflog (reference log) is a private diary of every place HEAD has pointed to in your repository: every commit, checkout, reset, merge and rebase. It exists only on your computer and keeps entries for at least 30 days for commits that are no longer on any branch (90 days by default for the rest). Here is where Priya’s portfolio stands:
git log --oneline -3Click Run to see what this code prints.
Undoing a Hard Reset
Meaning to drop one commit, she types HEAD~2 instead of HEAD~1:
git reset --hard HEAD~2Click Run to see what this code prints.
git log --oneline -3Click Run to see what this code prints.
Her two latest commits have vanished from the branch. But the reflog remembers where HEAD was:
git reflog -3Click Run to see what this code prints.
Read it top to bottom, newest first. HEAD@{0} is the reset she just did. HEAD@{1} is where she was immediately before it — her latest commit, “Limit page width and improve spacing”. (Entries like “reset: moving to HEAD” come from earlier git stash commands, which use a reset internally.) Resetting back to that entry restores everything:
git reset --hard HEAD@{1}Click Run to see what this code prints.
git log --oneline -3Click Run to see what this code prints.
The reflog only remembers commits. Edits that were never committed — wiped by git restore or git reset --hard — are gone for good. That is the strongest argument for committing small and often.
Recovering a Deleted Branch
Priya tries a heading animation on an experimental branch, commits it, returns to main and force-deletes the branch:
git switch -c experiment/animations# ...create animations.css...git add animations.cssgit commit -m "Add fade-in animation for heading"git switch maingit branch -D experiment/animationsClick Run to see what this code prints.
Git even printed the commit the branch pointed to: was 7ae3a04. If that message has scrolled away, the reflog has it too:
git reflog -3Click Run to see what this code prints.
A branch is only a label, so recreating it is one command — point a new label at that commit:
git branch experiment/animations 7ae3a04git branchClick Run to see what this code prints.
You ran git reset --hard HEAD~3 by mistake and lost three commits. git reflog shows HEAD@{1} is where you were before. How do you get the commits back?
Copying a Commit with cherry-pick
Priya decides the animation is good after all, but she does not want the whole experiment branch — just that one commit. git cherry-pick copies a commit onto the current branch as a new commit:
git cherry-pick experiment/animationsClick Run to see what this code prints.
git log --oneline -2Click Run to see what this code prints.
A branch name picks its latest commit; you can also give any commit ID, or several IDs at once. Cherry-pick is ideal for bringing one specific fix into a release branch. For whole features, merge instead — cherry-picking many commits creates duplicates with different IDs that are confusing later.
Finding a Bug with git bisect
Something broke, and you do not know which of the last fifty commits did it. git bisect performs a binary search through history: you mark one bad commit and one good commit, and Git checks out the commit halfway between. You test it and say good or bad; Git halves the range again. Fifty commits take only about six tests.
git bisect startgit bisect bad # the current commit has the buggit bisect good v1.0.0 # this release did not# Git checks out a commit in the middle. Test it, then run one of:git bisect goodgit bisect bad# ...repeat until Git names the first bad commit, then:git bisect resetIf you have an automated test that detects the bug, git bisect run <test-command> runs the whole search for you.
Habits That Prevent Disasters
- Commit small and often — anything committed can be recovered.
- Run git status before any command that discards work (restore, reset --hard, clean).
- Push your branches regularly, so a lost laptop never means lost work.
- Never rewrite shared history: revert instead of reset, and no force pushes to main.
- Keep secrets out of commits with .gitignore, and rotate anything that leaks.
- Store large binary files such as videos with Git LFS (Large File Storage), not as regular commits.
- Before trying anything risky, create a safety branch: git branch backup-before-rebase.
You think you lost commits. Put the recovery steps in order.
- Create a branch there or reset to it
- Check the result with git log
- Find the entry from just before the mistake
- Stop and do not run more destructive commands
- Run git reflog to see where HEAD has been
Common Mistakes
- Panicking and running more commands, which pushes the right reflog entry further down the list.
- Deleting and re-cloning a repository to “fix” it, losing local commits that were never pushed.
- Cherry-picking a long series of commits instead of merging the branch.
- Forgetting git bisect reset at the end, leaving the repository on an old commit.
Frequently Asked Questions
No. The reflog is local to each repository on each computer. If you need to recover something that only existed on GitHub, a teammate’s clone or GitHub support may be your best option.
It means HEAD points directly to a commit instead of a branch — for example after checking out a tag, or during bisect. You can look around freely; if you make commits you want to keep, create a branch with git switch -c <name> before switching away.
Practise the workflow on real projects: put your own work on GitHub, open pull requests, and make a small open-source contribution. Then learn continuous integration, which runs automated checks on every pull request.
Key Takeaways
- git reflog records every position of HEAD, so committed work can be found for weeks.
- git reset --hard HEAD@{n} returns to an earlier reflog entry.
- Recreate a deleted branch with git branch <name> <commit-id>.
- git cherry-pick <commit> copies a single commit onto the current branch.
- git bisect binary-searches history to find the commit that introduced a bug.
Summary
Congratulations — you have completed the Git & GitHub course. You can track changes, branch and merge, rebase safely, collaborate through pull requests, contribute to open source, mark releases, follow team workflows and recover from almost any mistake. Put it into practice with the projects on the course page, and make Git part of everything you build from now on.