症状
git checkout や git switch を実行したら「detached HEAD」と表示された。または git status で「HEAD detached at xxxxx」と表示されている。
結論:まずこれを確認
git statusで現在の HEAD 位置を確認する- 変更をコミット済みなら、ブランチを作成して救出する
- 変更がなければ、
git switch ブランチ名で元に戻る
操作フロー
flowchart TD
A[detached HEAD 状態] --> B{未コミットの変更あり?}
B -->|Yes| C[git stash で退避]
B -->|No| D{コミット済みの変更あり?}
C --> D
D -->|Yes| E[git branch 新ブランチ名 で救出]
D -->|No| F[git switch ブランチ名 で戻る]
E --> G[git switch 新ブランチ名]
G --> H[必要なら既存ブランチにマージ]
F --> I[解決]
H --> I
よくある原因
- 特定のコミットを checkout した -
git checkout コミットハッシュを実行した - タグを checkout した -
git checkout v1.0.0のようにタグを指定した - リモートブランチを直接 checkout した -
git checkout origin/mainを実行した - rebase 中に中断した - rebase 操作が途中で止まっている
- サブモジュールの更新 - サブモジュール内で特定コミットに切り替わった
- bisect 実行中 -
git bisectでバグ調査中の状態
操作手順
ステップ1: 現在の状態を確認する
git status
🔍 チェックポイント: 「HEAD detached at」または「HEAD detached from」と表示される
# 出力例
HEAD detached at a1b2c3d
nothing to commit, working tree clean
ステップ2: 未コミットの変更があれば退避する
git stash
🔍 チェックポイント: 「Saved working directory」と表示されれば退避完了
ステップ3: コミット済みの変更があるか確認する
detached HEAD 状態で新しいコミットを作成した場合、そのコミットを救出する必要がある。
git log --oneline -5
🔍 チェックポイント: detached HEAD 状態で作成したコミットがあるか確認する
ステップ4-A: コミットがある場合 - ブランチを作成して救出する
# 現在位置に新しいブランチを作成
git branch rescue-branch
# 作成したブランチに切り替える
git switch rescue-branch
🔍 チェックポイント: git status で「On branch rescue-branch」と表示される
必要に応じて、元のブランチにマージする:
git switch main
git merge rescue-branch
ステップ4-B: コミットがない場合 - 元のブランチに戻る
git switch main
または
git checkout main
🔍 チェックポイント: git status で「On branch main」と表示される
ステップ5: 退避した変更を復元する
stash した変更がある場合:
git stash pop
🔍 チェックポイント: 退避した変更がワーキングディレクトリに復元される
NG行動
- detached HEAD 状態でコミットしてそのまま別ブランチに移動する - コミットが孤立し、後で参照できなくなる可能性がある
- git checkout -f でブランチに戻る - 未コミットの変更が消える
- reflog を確認せずに諦める - 孤立したコミットも reflog から復旧できる
よくある質問(FAQ)
Q1: detached HEAD 状態でコミットした後、別ブランチに移動してしまった。コミットは消えた?
A: 完全には消えていない。git reflog でコミットハッシュを確認し、git branch 新ブランチ名 コミットハッシュ で救出できる。ただし、一定期間(デフォルト90日)が経過すると GC で削除される。
Q2: なぜ detached HEAD 状態になるの?
A: HEAD が特定のブランチではなく、直接コミットを指している状態。過去のコミットを確認したり、特定バージョンをテストするときに便利だが、そのままコミットすると孤立する。
Q3: rebase 中に detached HEAD になった場合は?
A: rebase が進行中の可能性がある。git rebase --abort で rebase を中止するか、git rebase --continue で続行する。
関連するトラブル
準備中
解決しない場合
- Git 公式ドキュメント - git-checkout
- 確認すべきログ:
git reflogで HEAD の移動履歴を確認 - 次に調べるキーワード: 「git reflog 復旧」「git orphan commit」「git gc prune」