Git の中身に近い話

あるプロジェクトに新しく人が増えた時に参照する用にまとめておきます。
Git の基本的なコマンドを理解していることが前提条件です。

SHA-1

Git は扱うオブジェクトを全て 160bit の SHA-1 ハッシュ値により識別しています。
これにより、Git は各種操作を高速に行えるようになっています。
また、オブジェクトがハッシュ値により識別されるため、オブジェクトの内容が変ればこの値も新たに計算されるため、全てのオブジェクトをイミュータブルに扱うことが出来る、ということでもあります。

Git のオブジェクト

Git には 4 つのオブジェクトがあります。

  • blob オブジェクト
  • tree オブジェクト
  • commit オブジェクト
  • tag オブジェクト

この 4 つのオブジェクトが組み合わさって、Git のリポジトリが構成されています。

blob オブジェクト

blob オブジェクトは、ファイルの内容のみを保持するオブジェクトです。
git add によってリポジトリに作成されます。


blob オブジェクトはファイルの内容しか保持していないため、blob オブジェクトのハッシュ値はファイル名やモードなどに左右されません。

tree オブジェクト

tree オブジェクトは、ディレクトリを表し、格納している blob オブジェクトと tree オブジェクトの情報を保持しています。
また、blob オブジェクトに対応するファイル名やモードもこのオブジェクト内に格納されています。
ファイルモード、名前、blob/tree オブジェクトの SHA-1 ハッシュ値の順番で格納されています。


tree オブジェクトのハッシュ値は、含まれる blob/tree オブジェクトが変ったり、ファイル名やモードが変ったりすると変ります。

commit オブジェクト

commit オブジェクトは、コミット時の情報を保持するオブジェクトです。
主に、git commit コマンドによって作成されます。


commit オブジェクトには、作業ツリーの最上位の tree オブジェクトのハッシュ値と、作成者の情報、作成日時、コミッタの情報、コミット日時、コミットメッセージが格納されています。
また、一番最初の commit オブジェクト以外は親の commit オブジェクトのハッシュ値も保持しています。
commit オブジェクトはコミット日時を含んでいるため、内容が同じだったとしても毎回異なるハッシュ値となります。


作成者とコミッタ、作成日時とコミット日時のように一見同じに見える項目があり、またほとんどの場合で同じ情報が入るのですが、両者には違いがあります。
作成者、作成日時は、そのコミットに含まれる blob オブジェクトや tree オブジェクトを作成した人・日時が入り、コミッタ、コミット日時にはそれを元にリポジトリに commit オブジェクトを作成した人・日時が入ります。
例えば、送られてきたパッチから commit オブジェクトが作られる場合や、他人のリポジトリから持ってきたものを rebase する場合などで、これらの情報に違いが出てきます。

tag オブジェクト

tag オブジェクトは、アノテーション付のタグの情報を保持するオブジェクトです。
git tag -a や git tag -m によって作成されます。
通常の git tag コマンドでは「軽量タグ」と呼ばれるタグが作成され、tag オブジェクトは作成されません。