DETACHED HEADとは、HEADが直接commitを参照している状態のことである。
まず、HEADとはGitの現在の状態を参照するポインタであり、.git/HEADというファイルに格納されている。通常であればHEADはブランチを参照しているため、ファイルの内容は以下のようになる。
$ cat .git/HEAD
ref: refs/heads/misuzu
“ref: refs/heads/misuzu” という表記により「ローカルにあるmisuzuというブランチを参照せよ」という意味になる。
さて、Gitで一つ前のコミットや特定のタグをチェックアウトすると、以下のメッセージが表示される。
# 一つ前のコミットをチェックアウト
$ git checkout HEAD^
## git switch -c test HEAD^ でも同じ結果になる
You are in 'detached HEAD' state. You can look around, make experimental
### 中略
HEAD is now at 699a255 first commit
この時のHEADの内容は以下のようになる。先ほどのメッセージの最後にある 699a255 というはHEADの内容のはじめの7文字である。
cat .git/HEAD
699a255c7012d3627db4585b1b532830ce58c5e8
DETACHED HEADだと何が悪いの?
この状態でcommitすると、commitした内容が迷子になる。
通常であればHEADはブランチをさしている。この状態でcommitすると、ブランチが常に最新のcommitを参照し、ブランチを経由して各commitにアクセスできる。
しかし、DETACHED HEADの状態でcommitすると、commitした内容を参照するポインタがHEAD意外に存在しなくなる。この状態でgit checkoutで別のブランチやcommitに移るとHEADもそれに合わせて内容が変わる。すると、DETACHED HEADの状態でcommitした内容を参照するものがなくなるため、探し出すことができなくなる。
DETACHED HEADを回避するには?
Detached HEADはブランチを介さずに直接commitを参照することで発生する。そのため、チェックアウトするときに、以下のようにブランチを作成すればDETACHEDにはならない。
$ git checkout -b test HEAD^
## git switch -c test HEAD^ でも同じ結果になる
また、Detached HEADになってる状態でも、以下のようにブランチを作成しHEADをそのブランチに移動させるようにすれば Detached HEADの状態は解消される。なお、最後のHEADは省略できる。
$ git checkout -b test HEAD
## git switch -c test HEAD でも同じ結果になる。
どこ情報?
git-checkoutのDETACHED_HEADのセクションに載っている。Gitのマニュアルはわかりにくいが、このセクションは比較的わかりやすい方である。
コメント