Scenario
Section titled “Scenario”You finished a feature on a branch, decided it was a dead end, and deleted the branch. An hour later the decision is reversed: that work is needed after all.
git branch no longer lists it. The commits appear to be gone.
They are not.
Objective
Section titled “Objective”Recover a deleted branch and its commits using the reflog, and understand why it works — so that the next time this happens for real, it is a two-minute fix rather than an afternoon.
Prerequisites
Section titled “Prerequisites”- Git installed (
git --version) - Familiarity with
git commitandgit branch - Understanding of HEAD helps, but the lab explains what you need
Starting state
Section titled “Starting state”Build a disposable repository with a branch worth losing:
mkdir -p /tmp/lab-recover && cd /tmp/lab-recovergit init -q .git config user.email "lab@example.com"git config user.name "Lab User"
echo "# Project" > README.mdgit add . && git commit -q -m "Initial commit"
git switch -qc feature/pricingecho "export const PRICE = 4200;" > pricing.jsgit add . && git commit -q -m "Add pricing module"echo "export const TAX = 0.2;" > tax.jsgit add . && git commit -q -m "Add tax calculation"
git switch -q maingit log --oneline --allYou should see three commits, two of them only on feature/pricing.
-
Delete the branch. Git will refuse a safe delete because the work is unmerged, which is itself informative:
Terminal window git branch -d feature/pricingExpected:
error: the branch 'feature/pricing' is not fully merged.Now force it:
Terminal window git branch -D feature/pricing -
Confirm it is gone.
git branchlists onlymain.git log --oneline --allno longer shows the two commits. -
Find the lost commits. Do not panic and do not run
git gc. Run:Terminal window git reflogRead the output before continuing. What does each line represent?
-
Identify the tip commit of the deleted branch — the entry whose message mentions the last commit you made on it (
Add tax calculation). -
Recover it by creating a branch at that commit:
Terminal window git switch -c feature/pricing <sha> -
Verify.
git log --onelineshould show all three commits, andlsshould showpricing.jsandtax.js.
Practice Mode (in your browser)
Educational Git simulator. Supports the commands needed for this exercise; it is not a complete Git installation. Nothing runs on your machine and nothing is sent anywhere — progress is kept in this browser only.
Objective: The branch `feature/pricing` was force-deleted with 2 unmerged commits on it. Restore it so it points at its last commit ("Add tax calculation") again. Estimated 5 minutes. Hints, a worked solution and a restart are available; success is checked against the repository state, so any correct route counts.
Open Practice Mode
Loading the simulator…
Keep building your Git skills. Get one practical technique, one workflow, and one security lesson each week. Modern Git Weekly is not taking subscriptions yet — read thesample issue, or follow new lessons by RSS.
Stuck on step 3? The reflog is a log of where HEAD has been, newest first. Deleting a
branch does not delete commits — it deletes a pointer to them. The commits are still in the
object database, just unreferenced.
Stuck on step 4? git reflog shows entries like a1b2c3d HEAD@{2}: commit: Add tax calculation. You want that SHA. You can also use the HEAD@{n} form directly.
Want to see it more directly? git fsck --lost-found lists unreachable objects — the same
commits, found a different way.
Solution
Section titled “Solution”git reflog# a1b2c3d HEAD@{0}: checkout: moving from feature/pricing to main# a1b2c3d HEAD@{1}: commit: Add tax calculation# 9f8e7d6 HEAD@{2}: commit: Add pricing module# 1a2b3c4 HEAD@{3}: commit (initial): Initial commit
git switch -c feature/pricing a1b2c3d# Switched to a new branch 'feature/pricing'
git log --onelinelsYour SHAs will differ — they are content-derived, so they are unique to your run.
Equivalent, using the reflog reference directly:
git switch -c feature/pricing HEAD@{1}Explanation
Section titled “Explanation”A branch is a file containing a SHA. refs/heads/feature/pricing held 41 bytes: a commit
hash and a newline. git branch -D deleted that file. It did not touch the commit objects.
The commits became unreachable, not deleted. Nothing pointed at them, so they were invisible
to git log and git branch — but they were still in .git/objects.
The reflog is the safety net. Git records every movement of HEAD in .git/logs/HEAD,
including movements away from commits that no branch references any more. That log is what makes
this recoverable.
Recovery is just creating a new pointer at the commit the reflog identifies.
What this does not cover: uncommitted changes. The reflog tracks commits. Work that was never committed is not in Git at all, and nothing here recovers it.
Clean up
Section titled “Clean up”cd /tmp && rm -rf lab-recoverRelated lessons
Section titled “Related lessons”Next lab
Section titled “Next lab”Resolve a merge conflict — create a genuine conflict and work through resolving it properly.
How did this go?
Unexpected output. Compare your output with the expected block line by line; the first differing line is usually the cause. Then check the version-sensitive notes.
Missing prerequisite. Most "stuck" moments here come from one earlier concept. The prerequisites list names it; the learning path puts it in order.
Unclear explanation. Read the explanation section, then the mental model, then retry the step — the command usually makes sense once the model is in place.
Instructions did not match my environment. Check `git --version` and your shell (Git Bash vs PowerShell vs zsh). Platform notes on the page name the differences that matter; the verification step confirms you are back to a known state.
Good. The next step is to do it without the page open — or move to the recommended next activity below.
All help on this page: Git troubleshooting decision tree · Prerequisites for this page · The explanation section · Recover a lost commit (lab)