HEAD とは何か・detached HEAD

《 Git & GitHub 完全ガイド 目次へ 》

このページで分かること

  • HEAD が「今いる場所」を指す名前だと分かる
  • HEAD → ブランチ → コミットという2段の指し方を説明できる
  • detached HEAD がどういう状態かが分かり、慌てずに戻れる
  • detached HEAD で作ったコミットを失わずに済む方法が分かる

第2部の14では、HEAD を「今いる位置、つまり最新のコミットを指す名前」として使いました。このページでは、その正体を開けて確かめます。HEAD が分かると、第4部のブランチの操作が「名前を付け替えているだけ」だと見えてきます。


HEAD はファイル1つ

HEAD の実体は、.git の中にある HEAD という名前のテキストファイルです。

cd ~/git-practice
cat .git/HEAD

# 出力:
# ref: refs/heads/main

中身は1行だけで、「refs/heads/main を見よ」と書いてあります。refs/heads/main は main ブランチのことで、その正体は第3部の19で開けます。ここでは「HEAD はコミットを直接指しているのではなく、ブランチを指している」ことだけ押さえます。

上段はふだんの状態で、HEAD が main を指し、main がコミット C を指す。下段は detached HEAD で、HEAD が main を通さずコミット B を直接指し、main は C を指したまま
上段はふだんの状態で、HEAD が main を指し、main がコミット C を指す。下段は detached HEAD で、HEAD が main を通さずコミット B を直接指し、main は C を指したまま

上段がふだんの状態です。HEAD は main を指し、main が最新のコミットを指します。HEAD と main のどちらで尋ねても、行き着くコミットは同じです。

git rev-parse HEAD
git rev-parse main

# 出力(2つとも同じ):
# b505e8e8f92abb8142a6ca486600de9100f98e42

git rev-parse は、名前がどのコミットを指しているかを ID で答えるコマンドです。

コミットすると何が動くのか

この2段の指し方には意味があります。コミットすると、Git はHEAD が指しているブランチを、新しいコミットへ進めます。HEAD のファイルの中身は ref: refs/heads/main のまま変わりません。HEAD は main を指し続け、main だけが1つ先へ動きます。

「今どのブランチで作業しているか」を HEAD が覚えていて、記録はそのブランチに積み上がる、という仕組みです。第4部の22でブランチを切り替えるときに動くのは、この HEAD の中身です。


detached HEAD:HEAD がコミットを直接指す状態

過去のコミットの状態を見たいとき、そのコミットに移動できます。

git switch --detach HEAD~2

# 出力:
# HEAD is now at 35b12cd やることに郵便局を追加

git switch は今いる場所を切り替えるコマンドで、--detach は「ブランチを通さず、コミットに直接移る」という指定です。HEAD の中身を見ると、変わっています。

cat .git/HEAD

# 出力:
# 35b12cd6e2f8655e722088f0cc635c3686230db0

ref: … ではなく、コミットの ID が直接書かれています。これが detached HEAD(切り離された HEAD)です。図の下段の状態で、HEAD がブランチから切り離されて、コミットを直接指しています。

git status

# 出力:
# HEAD detached at 35b12cd
# nothing to commit, working tree clean

ワークツリーのファイルは、そのコミットの時点の内容に変わっています。todo.txt を開くと「郵便局に行く」の行があり、recipes フォルダはありません。main ブランチのコミットは何も変わっていません。 見る場所を移しただけです。

補足

git checkout 35b12cd のように、git checkout にコミットの ID を渡しても detached HEAD になります。その場合は You are in 'detached HEAD' state. で始まる長い説明が表示されますが、起きていることは同じです。資料によっては checkout で説明されています。


元に戻る

見終わったら、ブランチに戻ります。

git switch main
cat .git/HEAD

# 出力:
# ref: refs/heads/main

HEAD が再び main を指し、ワークツリーも main の最新のコミットの状態に戻りました。detached HEAD はエラーではなく、ただの状態です。慌てる必要はありません。


注意:detached HEAD でコミットすると

detached HEAD のままでもコミットはできます。ただ、そのコミットを指すブランチがありません。

git switch --detach HEAD~2
echo "あとで消える行" >> todo.txt
git commit -a -m "迷子のコミット"
git switch main

# 出力:
# Warning: you are leaving 1 commit behind, not connected to
# any of your branches:
#
#   4d25345 迷子のコミット
# (以下略)

main に戻るとき、Git は「どのブランチにもつながっていないコミットを1つ置いていく」と警告します。git log には出てこなくなり、第2部の15で見たとおり、reflog からしかたどれなくなります。

残しておきたい場合は、detached HEAD のうちに、そのコミットにブランチの名前を付けます。

git switch -c rescue

git switch -c 名前 は、今いるコミットに新しいブランチを作って、そこに移るコマンドです。ブランチの作り方は第4部の22で扱います。もう戻ってしまったあとでも、警告に表示された ID(ここでは 4d25345)や reflog を使って、git switch -c rescue 4d25345 のように救えます。

今回の「迷子のコミット」は練習なので、救わずにそのままにしておいて構いません。


よくある疑問

Q. HEAD~1 と HEAD@{1} は何が違いますか?
A. HEAD~1 は「今のコミットの1つ前(親)」、HEAD@{1} は「HEAD が1回前にいた場所」です。前者は履歴のつながりを、後者は第2部の15の reflog をたどります。reset や switch のあとでは、2つが別のコミットを指すことがあります。

Q. detached HEAD は、どんなときに使うのですか?
A. 過去のある時点のファイルを丸ごと確かめたいときです。第5部の32の bisect(不具合が入ったコミットを探す機能)でも、Git が自動で detached HEAD を使います。


まとめ

  • HEAD は .git/HEAD というファイルで、ふだんはブランチの名前を指している
  • コミットすると、HEAD が指しているブランチが新しいコミットへ進む
  • detached HEAD は、HEAD がブランチを通さずコミットを直接指している状態
  • git switch ブランチ名 で戻れる。detached HEAD はエラーではない
  • detached HEAD で作ったコミットは、git switch -c でブランチを付けて残す

次のページ

19. 参照(refs)とブランチの実体 ── HEAD が指していた refs/heads/main を開けて、ブランチの正体が41バイトのファイルであることを確かめます。

→ ガイドの目次に戻る

この記事の最終確認日: 2026年10月

タイトルとURLをコピーしました