What's Actually Happening
A "detached HEAD" means Git's HEAD pointer is pointing directly to a commit hash instead of a branch name. Normally HEAD points to a branch (like main), which points to a commit. In detached state, HEAD points straight to a commit.
The Warning You'll See
```bash $ git checkout abc123 Note: switching to 'abc123'.
You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with: git switch - ```
Why This Happens
- 1.Checking out a commit hash -
git checkout abc123d - 2.Checking out a tag -
git checkout v1.0.0 - 3.Rebase operation - During interactive rebase
- 4.Checking out a remote branch without tracking -
git checkout origin/feature
Step 1: Check Your Current State
git statusShows:
HEAD detached at abc123d
nothing to commit, working tree cleanOr if you have changes:
HEAD detached at abc123d
Changes to be committed:
(use "git commit"...)
modified: src/app.jsStep 2: If You Haven't Made Changes
Just want to look at old code? No worries:
# Return to your previous branch
git switch -
# Or:
git checkout mainNothing lost - you were just viewing.
Step 3: If You Made Commits in Detached State
Critical: Save your work before switching away!
First, see what commits you made:
git log --oneline -5Shows your new commits on top of the detached point:
def4567 (HEAD) My experimental change
abc123d Original commit I checked outCreate a branch to save these commits:
```bash # Create branch from current detached HEAD git branch my-experiment
# Or use switch with -c git switch -c my-experiment ```
Now your commits are saved on my-experiment branch.
Step 4: If You Made Uncommitted Changes
If you edited files but haven't committed:
# Check what you changed
git status
git diffSave by creating a branch and committing:
git switch -c my-new-feature
git add .
git commit -m "Save work from detached state"Step 5: Recover Lost Commits (If You Already Switched Away)
If you panicked and switched away, losing commits:
# Check reflog for recent HEAD positions
git reflogOutput shows your movements:
abc123d HEAD@{0}: checkout: moving from def4567 to abc123d
def4567 HEAD@{1}: commit: My experimental change
abc123d HEAD@{2}: checkout: moving from main to abc123dFind your lost commit (def4567) and recover:
```bash # Create branch pointing to lost commit git branch recovered-work def4567
# Switch to it git switch recovered-work ```
Step 6: Understanding Reflog Recovery
Reflog keeps history of HEAD movements for ~90 days:
```bash # See all recent HEAD positions git reflog show HEAD
# Find specific action git reflog show HEAD --grep="commit" ```
Each entry shows where HEAD was, so you can return there.
Step 7: Intentional Detached HEAD Use
Sometimes detached HEAD is useful:
```bash # View old version of code git checkout v2.0.0
# Test against specific commit git checkout abc123d
# Start experiment without creating branch yet git checkout main~5 # 5 commits before main ```
Just remember: any commits you make need a branch to save them.
Verify the Fix
After creating branch and saving work:
```bash git status
# Should show: # On branch my-experiment # nothing to commit, working tree clean
git log --oneline -3 # Your commits should be visible ```
Prevention Tips
When checking out specific commits, use -c flag to create branch immediately:
```bash # Create branch while checking out commit git switch -c inspect-v1.0 v1.0.0
# Or with checkout git checkout -b inspect-v1.0 v1.0.0 ```
This avoids detached state entirely.