症状

git checkoutgit switch を実行したら「detached HEAD」と表示された。または git status で「HEAD detached at xxxxx」と表示されている。

結論:まずこれを確認

  1. git status で現在の HEAD 位置を確認する
  2. 変更をコミット済みなら、ブランチを作成して救出する
  3. 変更がなければ、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 で続行する。

関連するトラブル

準備中

解決しない場合