Git

Gitの参照 – HEADとheadsとtagsとremotes

投稿日:2016年11月30日 更新日:


Gitの参照についてまとめました。また別記事にてGitの内側について記載しています。

Gitの内側についておさらい

  • 「git init」すると「.git」ディレクトリができるがその中についてがテーマ
  • 普段は使わない配管コマンドと呼ばれる下位レベルのコマンドがある
  • 4つのオブジェクトがある
    • blobオブジェクト(ファイルに相当)
    • treeオブジェクト(ディレクトリに相当)
    • commitオブジェクト(commit情報を保持)
    • tagオブジェクト(Tagを保持)

Gitの参照って?

ここで取り上げるGitの参照は「HEAD」ファイルと「.git/refs」配下のことを示します。「git init」した直後「HEAD」ファイルは「refs/heads/master」を参照し(初期化直後はなにも存在しない)、「.git/refs」配下には、headsとtagsディレクトリがあります。ブランチにcommitするとheads配下にブランチ名のファイルができ、HEADファイルはheads配下のブランチ名を参照します。

Gitの参照の種類

Gitの参照の種類は次の通りです。

  • heads:作業中ブランチのcommitを参照
  • tags:commitをわかりやすくする為の名前付け用
  • remotes:リモートブランチのcommitを参照
  • HEAD:作業中のブランチに対するシンボリック参照。HEADは基本的にheadsを参照しているので、他の参照と区別する為シンボリック参照と呼ばれます

動作確認の為の事前準備

次のような3つのcommitがあるリポジトリを用意しremoteへpushしておきます。

次からはこのリポジトリを利用します。クローンする場合はこちらを利用してください。

構成

構成は次の通りです。「.git/refs」ディレクトリ配下にそれぞれheads, remotes, tagsというディレクトリが作られています。

Gitの参照の解説

「refs」配下にあるファイルはそれぞれ最後のcommitをファイルに記録しています。例えば現在masterは「third commit」にいますが「git log –pretty=oneline master」とすると次のようなcommit履歴が確認できます。

これはハッシュを指定した次のコマンド「git log –pretty=oneline 17fb14ac7c9493751cff838ba0c22897582406a5」と同じ結果です。「.git/refs/heads/master」ファイルにcommit情報が記述されている為同じ結果となります。

上記のことから「.git/refs/heads/master」にcommitのハッシュ値を指定することでmasterのheadが変更可能です。ただし直接操作は非推奨(通常操作することはありませんが)なので参照を変更する時は次のコマンドを使います。

「second commit」に変わりました。また次のコマンドはそこからブランチを切ることができます。

「.git/refs」ディレクトリの構成を見ていきましたので、次は「HEAD」ファイルと「.git/refs」を構成する各参照について解説します。

HEAD

HEADファイルは現在作業中のブランチを参照しています。「git branch (ブランチ名)」を実行したときは、HEADからブランチが切られます。HEADファイルは 「.git」直下に配置されます。

「git checkout test」を実行した内容は次の通りです。

このHEADファイルを確認したり変更するには次のコマンドを使います。

tags

tagはGitのオブジェクトでもあります。tagオブジェクトはcommitオブジェクトに似ていますが、treeではなくcommitを指し示します。また、tagには軽量 (lightweight) 版と注釈付き (annotated) 版の2つのタイプがあります。

軽量 (lightweight) 版

  • tagをつけられる
  • commitオブジェクトにtagがつく
  • tagオブジェクトではない

注釈付き (annotated)版

  • tagとコメントがつけられる
  • tagオブジェクトになる

軽量版は「second commit」のハッシュ値になのに対し、注釈付きは別のハッシュの値となっています。これはcommitに対する直接的な参照ではなく、tagオブジェクトがつくられた為です。また、refsの中は下記の通りです。

remotes

remoteもほぼ上記内容と同様の仕組みとなっています。では試しにtestブランチをremoteにプッシュしてみます。するとさっきまでなかった「.git/refs/remotes/origin/test」が追加されます。またその中身はtestブランチのHEADのハッシュです。これはつまりremoteを確認することで最後にoriginと通信したときの情報を取得できるということです。

まとめ

  • 参照にはheadとremoteとtagがある
  • HEADファイルは参照を参照し現在のブランチのシンボリックリンクを参照している
  • tagには軽量版と注釈付き版があり注釈付きの方がtagオブジェクトとなる
  • remoteは最後にサーバと通信したときのハッシュを保持している

Gitの参照と参照系の下位コマンドが確認できました。普段何気なく使っているコマンドの内側で何が行なわれてるかが分かっておもしろいですね。

参考


-Git
-

執筆者:

関連記事

Gitのソースコードをデバッグする

これまでGitの内側の仕組みなどをチェックしてきて、最近ようやくソースコードをデバッグしてみても処理が追えそうというところまできたので記事にまとめておきます。ただ色々試しながらやった結果なので、もっと …

Git 2.9でdiffがちょっとかしこくなった

ちょっと前にはなるがGit 2.9がリリースされてdiffがちょっとかしこくなった。 リリースノート Git 2.9 Release Notes 記事 Git 2.9 has been release …