sato.masaki

2014.12.21

Git の中身を見てみよう!vol.2 – Git オブジェクト (Advent Calendar 21日目)

こんにちは。アドベントカレンダー21日目を担当する佐藤(ま)です。
アライドでは「大佐」と呼ばれております。

前回に引き続き、git-scm.com の Book をみながら Git (.git) の中身をみていってみようと思います。今回は、前回も少し触れましたが、Git オブジェクトについてです。
10.2 Git Internals – Git Objects

Git Objects の種類

Git オブジェクトは、blob(ファイルに対応)、tree(ディレクトリに対応)、commit、tag の4種類ありますが、今回は主に、こちらでふれられてる blob、tree、commit object について確認していきます。

Blob Objects

Blob object は前回も少し触れましたが、ファイルに対応しているオブジェクトで、hash-object コマンドでオブジェクトを格納したり、cat-file コマンドでオブジェクトのタイプや中身を確認することができます。

Tree Objects

The next type we’ll look at is the tree, which solves the problem of storing the filename and also allows you to store a group of files together.

A single tree object contains one or more tree entries, each of which contains a SHA-1 pointer to a blob or subtree with its associated mode, type, and filename.

10.2 Git Internals – Git Objects より

Blob object だけだとコンテンツだけを格納していて、ファイル名が格納できないなどの問題がでてきますが、それらを解決するのに、tree object が使われます。では、適当にファイルとディレクトリをコミットし cat-file コマンドで tree object を確認してみます。

master^{tree} と指定することで master 配下の tree object を確認することができます。

配管コマンドで独自のツリーを作る

次に、配管コマンドだけで、blob object で書き込んだオブジェクトをステージングし、独自のツリーオブジェクトをつくってみます。ここでは、上記 Blob Objects で作成したオブジェクトを利用していきます。

ステージングされました。続いて tree object に書き出します。

これで tree object が書き込まれました。続いてもう一つ、同じファイルと新しいファイルを追加し新しい tree object をつくってみます。

この時点で2つの tree object が作成できました。さらにこれらは read-tree コマンドを使うことで、既存のツリーを、サブツリーとして読み込むことができます。

Commit Objects

Commit object は、他のオブジェクトが持っていない、いつ、どのような理由で、誰が保存したのかについての情報を保持します。これまでの tree objects にはそのような情報がないので commit-tree コマンドを使って付与していきます。

commit object には、その時点のスナップショットが記載されます。続いてコミットツリーを繋げる形でコミットしていきます。-p オプションで直前のコミットを参照します。

このようにすることで、3つの commit object が1つのツリーとなるので、git log で一連のコミットログとして確認することができます。

また、オブジェクト一覧をみてみると、blob、tree、commit object が3つずつできる為、合計9つのオブジェクトができているのが分かります。(ドキュメントでは 10個できていますが、ここでは’test content’を除いているので9つとなります。)

これで git add から git commit までの流れを確認することができました。ここまでくると Git のコアの仕組みや、配管コマンドがどういうものなのかがなんとなく見えてきますね。

明日は、aoyama の番です!