Skip to content

Lab: Recover a Lost Commit from a Detached HEAD

Lesson 2 of 6Beginner4 min readHands-On Git & GitHub Labs · Git Recovery Labs
Time10 minutes
LevelBeginner
You needLocal Git only — no GitHub account needed

You checked out an older commit to reproduce a bug — a perfectly normal thing to do. While there, you fixed it and committed. Then you switched back to main to carry on.

The fix is not on main. It is not on any branch. git log --all does not show it.

You committed on a detached HEAD, and Git told you so at the time. This lab is about noticing that message, and about what to do when you did not.

Make a commit on a detached HEAD, lose it, and recover it — and read the warning Git prints so that next time the recovery happens before the commit is lost.

  • Git installed (git --version)
  • Lab 01, or an understanding that a branch is a pointer
  • HEAD explains what “detached” means; the lab shows it
Terminal window
mkdir -p /tmp/lab-lost && cd /tmp/lab-lost
git init -q -b main .
git config user.email "lab@example.com"
git config user.name "Lab User"
echo "# Project" > README.md
git add . && git commit -q -m "Initial commit"
echo "v1" > app.txt
git add . && git commit -q -m "Add app"
echo "v2" > app.txt
git add . && git commit -q -m "Update app to v2"
git log --oneline

Three commits on main:

cb83610 Update app to v2
e273666 Add app
f5813f4 Initial commit
  1. Detach HEAD at the previous commit, as you would to inspect an older version:

    Terminal window
    git switch --detach HEAD~1

    Git says HEAD is now at e273666 Add app. Run git status and read the first line.

  2. Commit while detached. Pretend you found and fixed a bug here:

    Terminal window
    echo "hotfix" > fix.txt
    git add . && git commit -q -m "Emergency hotfix on detached HEAD"
    git log --oneline

    The new commit is at the top. Its parent is e273666, not main’s tip.

  3. Switch back to main and read everything Git prints:

    Terminal window
    git switch main

    Do not skip the output. Git is telling you exactly what is about to happen and how to prevent it.

  4. Confirm the commit is gone from every branch:

    Terminal window
    git log --oneline --all

    Three commits. The hotfix is not listed. Is it deleted?

  5. Find it. Two tools will show it — try both:

    Terminal window
    git reflog
    git fsck --lost-found
  6. Recover it by putting a branch on it. Use the SHA from either command:

    Terminal window
    git branch hotfix <sha>
    git log --oneline --all

After step 6, git log --oneline --all lists four commits and git branch shows hotfix. Run git switch hotfix && lsfix.txt is there.

Step 3. The warning begins Warning: you are leaving 1 commit behind. It names the commit and prints the recovery command. Most people never read it because it appears at the moment they have already decided to move on.

Step 5. The reflog records every movement of HEAD, including the commit you made while detached and the switch away from it. git fsck --lost-found finds the same commit a different way: by looking for objects nothing references.

Step 6. git branch <name> <sha> creates a branch without switching to it. git switch -c would also work and switch as well.

Step 3’s output, in full:

Warning: you are leaving 1 commit behind, not connected to
any of your branches:
291d542 Emergency hotfix on detached HEAD
If you want to keep it by creating a new branch, this may be a good time
to do so with:
git branch <new-branch-name> 291d542
Switched to branch 'main'

The reflog, after the switch:

cb83610 HEAD@{0}: checkout: moving from 291d542860f8df289c3475d4ec2722b0a439252c to main
291d542 HEAD@{1}: commit: Emergency hotfix on detached HEAD
e273666 HEAD@{2}: checkout: moving from main to HEAD~1
cb83610 HEAD@{3}: commit: Update app to v2
e273666 HEAD@{4}: commit: Add app
f5813f4 HEAD@{5}: commit (initial): Initial commit

HEAD@{1} is the commit. Note that HEAD@{0} says “moving from 291d542…” — a raw SHA rather than a branch name, because there was no branch.

git fsck --lost-found:

dangling commit 291d542860f8df289c3475d4ec2722b0a439252c

Recovery:

Terminal window
git branch hotfix 291d542
git log --oneline --all
291d542 Emergency hotfix on detached HEAD
cb83610 Update app to v2
e273666 Add app
f5813f4 Initial commit

Your SHAs will differ.

Detached HEAD means HEAD points at a commit, not a branch. Normally HEAD contains ref: refs/heads/main and committing moves main. When HEAD contains a raw commit ID, committing moves HEAD itself — and nothing else. No branch advances.

Switching away leaves the commit with no pointer. It is not deleted; it is unreachable from any ref. git log --all walks from refs, so it cannot see it. The reflog, which records HEAD’s movements rather than walking the graph, still can.

Git warned you. The “leaving commits behind” message is printed precisely when a switch would strand commits. It includes the recovery command. Reading it turns a recovery into a non-event.

The safe habit: if you are going to commit while detached, create a branch first — git switch -c fix-attempt — and the question never arises.

git switch main printed no warning. You committed nothing while detached, so there was nothing to leave behind. Repeat step 2.

The reflog does not show the commit. You may be reading a different repository’s reflog — check pwd. The reflog is per-repository and per-clone.

git branch hotfix <sha> says “not a valid object name”. The SHA was mistyped. Copy it from the reflog; the seven-character prefix is enough.

Terminal window
cd /tmp && rm -rf lab-lost

Undo a bad merge — two different fixes for the same mistake, depending on whether anyone has seen it.

Choose a learning pathA sequenced route through the curriculum for wherever you are now.