gitのcommit objectの中身

commitって結局なんなの?というはなしです.commitの中身を表示してデータの実体を見てみます.

あわせて読みたい: Git for Computer Scientists

適当なcommitのobject id ( = SHA1 )を得るためにgit show-refでmasterブランチのHEAD commitのobject idを得ます.

$ git show-ref  refs/heads/master # master の HEAD の commit の obeject id を表示
216640790e88d6fd794a96fd1a7c81dd2ad86981 refs/heads/master

以下のようにして,git cat-file でcommitの内容を表示できます.treeにはcommitが発生した時点でのファイルツリーを再現するための情報が入っています.parentはこのcommitの親にあたるcommitです.

$ git cat-file commit 216640790e88d6fd794a96fd1a7c81dd2ad86981 # commit の中身を表示
tree adb285a47d87f238c7ae64cac70222821084b8dd             # commit に対応する tree の object id
parent 3e8ba4bffdc7b36b85f99538558623faabcdaf24           # 親 commit の object id
author hakobe932 <hakobe@gmail.com> 1234567890 +0900      # 作者?
committer hakobe932 <hakobe@gmail.com> 1234567890 +0900   # コミッタ

ahe をコミットしたよ!                                    # コミットログ

さらに,git ls-tree で tree の中身を表示できます.blobは普通のファイルです.treeはディレクトリです.それぞれ対応する object id で実体を取得できます.treeの中身をみるには同様にgit ls-treeを使います.blobの中身をみるにはgit cat-fileを使います.

$ git ls-tree adb285a47d87f238c7ae64cac70222821084b8dd # tree のなかみを表示
100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99	ahe
100644 blob 65a228ae78d3c7abae20edcfb141d2443bedb893	puu
040000 tree 06d399b211ed3468cd32b294795f8bc8ae83b0e4	bin
$ git cat-file blob 65a228ae78d3c7abae20edcfb141d2443bedb893 # blob のなかみを表示 (masterのHEADでの cat puu と等価)
puu
aheahe heheheh-!
howhow

このように?,commit がわかれば commit に対応する tree が得られます.treeにはそのcommitが行われた段階でのファイルツリーの情報が入っているので,いつでもそのファイルツリーを再現できます.commitのparentをたどればこれまでにどのような変更がなされてきたかもわかります.

こうやってみると,シンプルでわかりやすいデータ構造によってgitのcommitが記録されているのがわかりますね.object idがいちいち長くてみずらいけど.

ちなみに

object は .git/objectsに記録されています.たとえば,65a228ae78d3c7abae20edcfb141d2443bedb893 という objectは .git/objects/65/a228ae78d3c7abae20edcfb141d2443bedb893 に記録されてます.object idの最初の二桁がディレクトリ名になってます.

object id は ファイルやツリーやコミットを一意に特定する必要があるのでかぶってはいけないのですが,40桁のSHA1 hex だと 1極4615載0163正7330澗9029講1820壌3684杼8327垓1628京3019兆6559億3254万2976 の id を表現できるので,ハッシュ関数をうまくつくればそうそうかぶらなさそうです.