Git detached HEAD状態とは — 抜け方とコミットの救出
detached HEADとは、HEADがブランチ名ではなくコミットを直接指している状態です。 リポジトリが壊れた状態やGitのエラーではなく、過去のコミットを調べたり一時的に試したりするための 正常な機能です。見るだけなら、そのまま元のブランチへ戻って問題ありません。
A detached HEAD means that HEAD points directly to a commit instead of a branch name. It is a normal Git state for inspecting or testing an exact revision, not repository corruption.
TL;DR
- 何もコミットしていなければ
git switch -またはgit switch mainで戻る - detached中にコミットし、まだその場にいるなら
git switch -c rescue/detached-workでブランチ化する - すでに離れたなら
git reflogでハッシュを探し、git branchで参照を作る - CIが特定コミットをチェックアウトしている場合のdetached HEADは通常の動作
1. HEADとブランチの関係 / What detached means
通常、参照の関係は次のようになっています。
HEAD → main → 5a6c007git commitを実行するとmainが新しいコミットへ進み、HEADは引き続きmainを通してそのコミットを指します。一方、detached HEADでは次の状態です。
HEAD → 5a6c007
main → 9b24d31現在のコミットは確認できますが、HEADとローカルブランチ名は結び付いていません。この状態でもgit status、git log、ビルド、テスト、コミット等は実行できます。 注意が必要なのは、ここで作ったコミットをブランチへつなげず別の場所へ移動するときです。
2. どういう操作でdetached HEADになるか
git checkout <ハッシュ>: ブランチ名ではなく特定コミットを直接チェックアウトするgit checkout <タグ>: タグが指すコミットをチェックアウトするgit checkout origin/main: ローカルブランチではなくremote-tracking branchを直接チェックアウトするgit bisect: 不具合を含むコミットを二分探索する間、候補コミットを順にチェックアウトする- CIでのチェックアウト: ブランチ先端ではなく、ビルド対象の正確なコミットを再現するためにコミットを直接チェックアウトする
git checkout mainのようにローカルブランチへ移る場合、HEADはそのブランチへ接続されます。origin/mainはリモートの状態を記録する参照であり、同名のローカルブランチmainとは別です。
3. 実際の警告文と読み方
Git 2.53.0.windows.2でテスト用リポジトリを作り、git checkout 5a6c007を実行すると 次の警告を確認できました。ハッシュとコミットメッセージ以外は実出力です。
Note: switching to '5a6c007'.
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 -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at 5a6c007 base commit前半は「閲覧、実験、コミットはできる」と説明しています。後半は、作ったコミットを残すならgit switch -c <new-branch-name>でブランチを作り、元へ戻すだけならgit switch -を使うという案内です。警告を消す設定も表示されますが、意味を理解する前に 無効化する必要はありません。
4. 何もしていない場合の抜け方 / Leave safely
調査やテストだけでコミットしていなければ、次のどちらかでブランチへ戻ります。
# 直前にチェックアウトしていた場所へ戻る
git switch -
# 戻るブランチを明示する
git switch maingit switch -は直前のチェックアウト先へ戻る指定です。直前の場所も別のコミットだった場合は ブランチへ戻らないため、戻り先が分かっているならブランチ名を明示します。作業ツリーに変更がある場合は 先にgit statusとgit diffで内容を確認してください。切り替え先と衝突する変更があれば、 Gitはチェックアウトを拒否します。
5. まだdetached HEAD中ならコミットごとブランチ化する
detached HEAD中に必要なコミットを作り、まだそのコミットから離れていない場合は、 現在地で新しいブランチを作るのが最短です。
git status
git log --oneline -3
git switch -c rescue/detached-workgit switch -cは現在のコミットを指す新しいブランチを作り、そのブランチへ切り替えます。 detached中に作った一連のコミットと作業ツリーはそのままです。確認後、必要なら通常どおりpushします。
git push -u origin rescue/detached-work6. すでに離したコミットはreflogから救出する
detached中のコミットからmainへ戻り、git logで見えなくなっても、すぐ消えたとは限りません。 まずHEADの移動履歴をreflogで確認します。
git reflog --oneline
5a6c007 HEAD@{0}: checkout: moving from 02ffecf21a5cf0001308c0b46ec8bbe3b13c3f3e to main
02ffecf HEAD@{1}: commit: detached work
5a6c007 HEAD@{2}: checkout: moving from main to 5a6c007
5a6c007 HEAD@{3}: commit (initial): base commitこれは同じテスト用リポジトリで実測した出力です。HEAD@{1}のcommit: detached workが救出対象で、短縮ハッシュは02ffecfです。 内容を確認してからブランチ参照を作ります。
git show --stat 02ffecf
git branch rescue/detached-work 02ffecf
git switch rescue/detached-work複数の候補がある場合は、メッセージだけで決めずgit showで差分、日時、親コミットを確認します。 コミットの取り消しやreset後の救出も含めた使い分けはgit commitを取り消す方法も参照してください。
7. コミットはいつ消えるか
ブランチ、タグ、HEAD等の参照から到達できないコミットは、Gitのガベージコレクション対象になります。 ただし、detached HEADから離れた瞬間にオブジェクトが削除されるわけではありません。HEADのreflogに移動履歴が残っている間は、 そのハッシュを探せる可能性があります。
Gitでは、現在の参照先から到達不能なreflogエントリの有効期限gc.reflogExpireUnreachableは既定で30日です。これは「30日間の復元を保証する」意味ではありません。 リポジトリ設定、手動のgit reflog expire、reflogの有無、ガベージコレクションの実行状況で保持期間は変わります。 必要なコミットを見つけたら、期限を当てにせずすぐブランチやタグで参照を作ってください。
8. CIログのdetached HEADは通常の動作
CIは、ブランチが後から進んでも同じソースをビルドできるよう、ジョブの対象となるコミットを直接チェックアウトすることがあります。 そのためログにdetached HEADが出ても、ビルドやテストだけを行うジョブなら通常は問題ありません。
一方、CI内でコミットを作成してpushする処理は、push先ブランチを明示する必要があります。 ブランチへ反映する処理では、対象ブランチの最新状態との関係も確認してください。履歴の統合方法はgit rebaseとmergeの違い、pushが拒否された場合はgit push rejectedの直し方で整理しています。
9. 救出後に統合するときの確認
救出ブランチを作った後は、まずgit log --oneline --decorate --graphでmainとの分岐を確認します。 mergeやrebaseで競合した場合、detached HEADの問題はすでに解決済みで、以降は通常の競合解消です。Gitマージコンフリクトの解消手順に従って、競合箇所を確認してから続行します。
git log --oneline --decorate --graph --all
git switch main
git merge rescue/detached-workEnglish summary
Detached HEAD is a normal state in which HEAD points directly to a commit. If you made no commits, return with git switch - or switch to a named branch. If you committed and have not moved away, run git switch -c rescue/detached-work. If you already left, find the commit with git reflog, inspect it with git show, and create a reference with git branch rescue/detached-work 02ffecf.
よくある質問 / FAQ
- detached HEADとは何ですか?
- HEADがブランチ名ではなく特定のコミットを直接指している状態です。過去の状態の調査やテストに使えるGitの正常な機能で、リポジトリが壊れたことを意味しません。
- detached HEADを解除して元のブランチへ戻るには?
- 直前にチェックアウトしていた場所へ戻るならgit switch -、戻るブランチが分かっているならgit switch mainのようにブランチ名を指定します。未コミット変更がある場合は、切り替え前にgit statusで確認してください。
- detached HEADの状態で作ったコミットを残すには?
- まだdetached HEADから離れていなければgit switch -c rescue/detached-workを実行し、現在のコミットを指す新しいブランチを作ります。コミットと作業ツリーを保ったまま通常のブランチへ移れます。
- detached HEADから離した後、見えなくなったコミットを救出できますか?
- git reflog --onelineでdetached中のcommit行を探し、git showで内容を確認してから、git branch rescue/detached-work <ハッシュ>でそのコミットを指すブランチを作ります。reflogの期限切れやガベージコレクション後は救出できない場合があります。
- detached HEADのコミットは30日で必ず消えますか?
- 必ず30日で消えるわけではありません。到達不能なreflogエントリの既定の有効期限が30日であり、実際の保持期間は設定、参照の有無、reflogの期限切れ、ガベージコレクションの実行状況で変わります。必要なコミットにはすぐブランチを作ってください。
- Is detached HEAD an error in CI?
- Usually no. CI systems often check out an exact commit for a reproducible build, which can intentionally leave HEAD detached. It matters only when the job needs branch-specific operations such as creating and pushing commits.