数年前にPro Gitを読んだ時のまとめが一部下書きに残っていたので、供養として投稿
何のメモか?
.git/objects配下のファイル間の関係についてのメモ
オブジェクトについて
UNIXはあらゆるものがファイルオブジェクトなのだが、Gitでもそれを踏襲している
commitによっていくつかのオブジェクト、もといファイルが生成される
具体的にはcommitオブジェクト、treeオブジェクト、blobオブジェクトができる(厳密には異なるが)
blobオブジェクトは「ファイル」
treeオブジェクトは「ディレクトリ構造」にあたる
これらオブジェクトの実体は、.git/objects配下に存在するファイルである
オブジェクトファイルの正体
.git/objects配下のファイルをテキストエディタで開いてみると、16進数40文字で命名されたファイルが存在する
中身はファイルの内容と不可分のハッシュ値だ
blobにはディレクトリ名と「ファイル」の中身をzlibで圧縮したものが書き込まれている
blobの名前は「ファイル」の中身のハッシュ値(SHA-1)なので、blobの名前と中身は不可分なものになる(天文学的な確率を除く)
blobは元の「ファイル」の名前やパーミッションなどのメタ情報を持たない
そういうものはtreeオブジェクトが保持している
treeには、blobのメタ情報と参照、子treeの参照が記述されている
では、rootとなるtreeの所有者やパーミッションなどの情報は誰が持っているのか
実は、commitオブジェクトが保持している
commitオブジェクトには、rootなtreeへの参照、親commitオブジェクトへの参照、コミット履歴のメッセージ、タイムスタンプなどが記述されている
このような構造で何が起きるかというと
blobオブジェクトに変更が加わると、ファイル名のハッシュ値が変わる。そのため、そのblobのハッシュ値を参照するtreeに変更が加わる
すると、treeのファイル名のハッシュ値も変わる。そして、そのtreeの親treeにも変化が加えられていき、rootなtreeまで変更される
そして、rootなtreeのメタ情報を持つcommitにも変更が加えられ、終いにはrootなcommitオブジェクトにも変更が波及するわけだ
感想
blobオブジェクトに変更が加わると、それが回り回ってcommitオブジェクトにまで波及する点が非常によく出来ている