LINEで現役エンジニアに直接質問してみよう!登録無料

git headとは?使い方と具体例を同時に解説 & 「detached head」からHEADをもっと深く理解する

アキ

独学でプログラミングを勉強しながらWeb制作会社で働き、プログラミングのエンジニア講師も勤めた経験がある、アキです。

  • GitのHEADって何?
  • HEADは具体的にどのように使えばいいの?

こんな疑問に答えます。

git headとは?

gitのHEADとは、「今のいる最新のコミット」の事を表します。つまり、「git show HEAD」とすれば、最新コミットの情報を見ることが出来ます。

ディレクトリで言うところの「カレントディレクトリ」と感覚が近いかもしれません。 カレントディレクトリの概念を使うと、そこから相対的な位置を表すことが出来ます。

git HEADも同じように、相対的にコミットのいちを表したいときによく用いられます。

git headの使い方(基本)

gitの今いるコミットの位置「HEAD」から相対的なコミット位置を表すには2種類の方法があります。

  • ~(チルダ)
  • ^(ハット または キャレット)

「HEAD^2」「HEAD~1」のように「HEAD + ^または~ + 数字」でコミットの位置を表します。

~(チルダ)を使ったコミットの指定方法

~(チルダ)は、「単に過去のコミットにさかのぼりたい時」に使われます。

1つ前にさかのぼりたい時はHEAD~1とします。1は省略することができるので、HEAD~がよく使われます。

# 1つ前を表す
HEAD~1
HEAD~ #1は省略可能

2つ前にさかのぼりたい時は下記のようにします

# 2つ前を表す
HEAD~2
HEAD~~

3つ、4つ前にさかのぼりたい時は下記のように繰り返します。

# 3つ前を表す
HEAD~3
HEAD~~~

# 4つ前を表す
HEAD~4
HEAD~~~~

^(ハット または キャレット)を使ったコミットの指定方法

^(ハット または キャレット)は、「マージなどで複数の親を持っているコミットにおいて、遡るコミットを選択したい場合」に使用します。

gitでHEADを使った例を紹介! 具体例を確認してHEADを使いこなそう

git reset head

git resetはリポジトリをある状態まで取り消すコマンドです。

このコマンドとHEADを組み合わせることで、最新のコミットから一つ前のコミットに戻すことが簡単に出来るようになります。

git resetには3つのオプションがあります。

  • --soft ・・・ コミット削除、インデックスそのまま、ファイルそのまま
  • --mixed ・・・ コミット削除、インデックス削除、ファイルそのまま
  • --hard ・・・ コミット削除、インデックス削除、ファイル削除

--soft``--mixed``--hardの順に情報が多く削除されます。通常は--softを使いましょう。コマンドラインで--hardは使うべきではありません。

git resetで直前のコミットまで取り消したい(コミットのみ削除)

$ git reset --soft HEAD~

git addを取り消したい(インデックスを取り消したい)

$ git reset --mixed HEAD
# または
$ git reset HEAD

直前のコミットまでの情報をすべて消したい

$ git reset --hard HEAD~2

git checkout head

git checkoutは、作業ディレクトリ内のファイルをコミットの情報を元にある状態まで戻すコマンドです。

あくまで、コミットを読み出しているだけなので、git resetのようにリポジトリ履歴を編集するわけではありません。

作業ディレクトリ内を直前コミットの状態に戻したい時

$ git checkout HEAD~

作業ディレクトリ内のあるファイルだけを、直前のコミット状態に戻したい時

$ git checkout HEAD~ -- file.txt

※ ただし、直前のコミットでfile.txtが編集されていないなら、コマンドが何回実行されても作業ディレクトリ内のファイルが変更されることはありません。

git diff head

git diffは、どのような変更をされたか(差分)を確認することが出来るコマンドです。

最新のコミットと今の状態の差分を確認する

$ git diff HEAD

2つ前のコミットと1つ前のコミットの差分を確認する

$ git diff HEAD~~..HEAD~
# または
$ git diff HEAD~2..HEAD~

最新のコミットから今の状態までの差分を1ファイルのみ確認する

$ git diff HEAD -- file.txt

git revert head

git revertは依存のコミットを打ち消すためのコマンドです。取り消しではありません。打ち消しです。つまり、その変更がなかった状態になるように、新しくコミットを作成します。

もし、過去のある変更で致命的なバグがあったて、そのコミットを取り消したいとします。gitは大抵、複数人で開発しているので過去のコミットを改ざんすると、開発者は全員一度作業を止めて新しいコミットにつなげるように変更しないといけません。これでは大変な労力がかかってしまいます。

こんなときにgit revertを使います。git revertは新しくコミットを積み上げるだけなので、そのままpullmergeを行うことが出来ます。

最新のコミットを打ち消したい時

$ git revert HEAD

「detached head」を理解してHEADについてもっと詳しくなる

今までは、HEADを使って「〇〇個前のコミット」みたいに指定する方法を学びました。「HEAD」と似た言葉に「detached head」と呼ばれるものもあります。 これを理解できると、HEADの理解がもっと深まるので、同時に学んでいきましょう。

「detached head」とは、「切り離されたHEAD」であり「無名ブランチ」である

「detached head」とは、簡単に言うと「ブランチ名やタグ名など何も関連付けられていない取り残されたコミットがある」という意味です。

そのコミットが存在すると、次のような問題が起こります。

  • 後からコミットを見つけようとしても、関連付けが無いので検索が難しくなります
  • コミットの指定方法はハッシュしかありません
  • git pushすることはできません
  • git pullして更新することはできません

もし、「detached head」になってしまった場合、下記のようなメッセージが表示されます

Warning: you are leaving 1 commit behind, not connected to
any of your branches:

  c642e2a Update config.yml

If you want to keep it by creating a new branch, this may be a good time
to do so with:

 git branch <new-branch-name> c642e2a

Switched to branch 'master'
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

このような時、下記のように実行すればブランチが作成され、問題は解消されます。

$ git branch <new-branch-name> c642e2a
この記事を書いた人

自身がプログラミングを独学で勉強し始めて躓いた経験を元に、これから勉強をする人に向けに「イラスト多めでわかりやすい記事」にこだわって情報を発信しています。

現在はフルスタックエンジニアとしてサービス開発などのお仕事をしています。