pubDate: 2024-03-04
author: sakakibara
gitは天才が作ったのか?
Linus Torvaldsはlinuxを作る際に既存のバージョン管理システムが気に入らなかった。
そして自分で作ったと言われている。それがgitだ。
gitを使いこなすには一定のハードルがある。
ステージング?インデックス?bolb?ツリー?
オブジェクトがどれも抽象的でわかりにくいのだ。
いくらlinusが天才だったとはいえ、このようなものをはじめから作成できたかは疑問だ。
だから、過去を探索してみることにした。
git-0.01
git-0.01は2005年4月7日にリリースされたおよそ1.2MBのプログラムだ。
そのREADMEには以下のように書かれている。
なぜかやけにテンションが高い。
何回stupidって言ってるんだこの人。
‘git’という単語に意味は無い。
使用者が雰囲気で決めていいらしい。
私はgitをgoddamn idiotic truckload of sh*t
と意味づけるとしよう。
そして、最後の文についてLinusのgitに対する哲学(後にUNIX哲学となる)が見て取れる。
Gitは愚直な(しかし、かなり早い)directory content managerである。
多くのことはできないが、directory contentsを効率的に追跡する。
そしてREADMEはこう続く。
2つの抽象的なobjectがある。object databaseとcurrent directory cahceだ。
Object database
object databaseは文字通り、ただのコンテンツ-アドレス可能なオブジェクトのコレクションである。
全てのオブジェクトはそれらの内容(コンテンツ)で名前付けられる。
つまり、オブジェクトはオブジェクトそれ自体のSHA1ハッシュで近似される。
オブジェクトは(SHA1を参照することにより)その他のオブジェクトを参照することができ、オブジェクトの階層構造を構築することができる。
驚いた。この頃からgitの基本的な構造は変わっていない。
つまり、ファイルの変更を追跡するためにファイルのSHA1ハッシュを取り、そのハッシュを参照することでファイルの変更を追跡しているのだ。
コンテンツアドレス可能なコレクションデータベースには、いくつかの種類のオブジェクトがある。
これらはすべてzlibでデフレートされ、そのタイプのタグとデータのサイズ情報で始まります。
SHA1ハッシュは常に、圧縮されたオブジェクトのハッシュであり、元のオブジェクトのハッシュではありません。
すべてのオブジェクトは、
(a)そのハッシュがファイルの内容と一致し、
(b)そのオブジェクトが + + + + のシーケンスを形成するバイトストリームに正常に展開されることを検証することで、
検証することができます。
BLOB:「ブロブ」オブジェクトは、データのバイナリ・ブロブに過ぎず、他の何かを参照することはない。
データには署名もその他の検証もないので、オブジェクトは一貫しているが(sha1ハッシュでインデックス付けされているので、データ自体は間違いなく正しい)、それ以外の属性はまったくない。
名前の関連もパーミッションもない。
純粋にデータの塊(つまり通常は「ファイルの内容」)である。
ツリー:次の階層オブジェクト・タイプは、“ツリー “オブジェクトです。
ツリー・オブジェクトは、パーミッション/名前/ブロブ・データを名前順に並べたリストです。
言い換えれば、ツリーオブジェクトはセットの内容によって一意に決定されるため、2つの別々の、しかし同一のツリーは、常にまったく同じオブジェクトを共有することになります。
繰り返しますが、“ツリー “オブジェクトは純粋なデータの抽象化に過ぎません。履歴も署名も正当性の検証もありませんが、ハッシュ自体によってコンテンツが再び保護されることを除いては。
つまり、ツリーの中身は、ブロブの中身と同じように信頼できるが、その中身がどこから来たのかはわからない。
チェンジセット チェンジセット “オブジェクトは、歴史という概念を取り入れたオブジェクトだ。
他のオブジェクトとは対照的に、単にツリーの物理的な状態を記述するだけでなく、どのようにしてそこに到達したのか、そしてなぜそうなったのかを記述します。
チェンジセット “は、その結果のツリーオブジェクト、その時点に至るまでの親チェンジセット(0個、1個、またはそれ以上)、そして何が起こったかのコメントによって定義されます。
繰り返しますが、チェンジセットはそれ自体信頼されるものではありません。
すべてのレベルで暗号的に強力な署名があるため、内容は明確に定義され「安全」ですが、ツリーが「良い」ものであると信じる理由も、マージ情報が意味を持つものであると信じる理由もありません。
例えば、親が結果と実際に何らかの関係を持つ必要はない。
信頼:「信頼」という概念は「git」の範囲外ですが、いくつか注意すべき点があります。
まず第一に、すべてがSHA1でハッシュ化されているので、オブジェクトが無傷であり、外部ソースによっていじられていないことを信頼することができます。
つまり、オブジェクトの名前は、既知の状態を一意に識別する。
さらに、チェンジセットのSHA1署名は、それが関連付けられたツリーのSHA1署名と親の署名を参照するので、一つの名前のチェンジセットは、全内容を含む一連の履歴を一意に特定します。
いったんチェンジセットの名前を知ってしまうと、あとからどのステップもごまかすことはできない。
ですから、システムに本当の信頼を導入するために必要なことは、トップレベルのチェンジセットの名前を含む、たった一つの特別なメモに電子署名をすることです。
あなたのデジタル署名は、あなたがそのチェンジセットを信頼していることを他の人に示し、チェンジセットの履歴の不変性は、その履歴全体を信頼できることを他の人に伝えます。
current directory cache
カレントディレクトリキャッシュ」は単純なバイナリファイルであり、任意の時点における仮想ディレクトリの内容を効率的に表現したものを含んでいる。
これは、名前、日付、パーミッション、コンテンツ(別名「ブロブ」)オブジェクトのセットを関連付ける単純な配列によって行われます。
キャッシュは常に名前順に並べられ、名前はどの時点でも一意である。
しかし、キャッシュには長期的な意味はなく、いつでも部分的に更新することができる。
特に、“カレント・ディレクトリ・キャッシュ “は、確かにカレント・ディレクトリの内容と一貫している必要はないが、2つの非常に重要な属性を持っている:
(a)キャッシュされた状態をすべて再生成できる(ディレクトリ構造だけでなく、“blob “オブジェクトを通してデータも再生成できる)。
特別なケースとして、カレント・ディレクトリ・キャッシュから “ツリー・オブジェクト”への明確で曖昧さのない一方向のマッピングがあります。
そのため、ディレクトリキャッシュは、いつでも一意に、ただ一つの「ツリー」オブジェクトを指定する(しかし、そのツリーオブジェクトとディレクトリで起こったことを簡単に照合 するための追加データを持っている)。
そして
(b)キャッシュされた状態(「インスタンス化待ちのツリーオブジェクト」)と現在の状態との間の矛盾を見つけるための効率的なメソッドを持っている。
ディレクトリキャッシュが行うことはこの2つだけです。
これはキャッシュであり、通常の操作は、既知のツリーオブジェクトから完全に再生成するか、開発中のライブツリーと更新/比較することです。
ディレクトリキャッシュを完全に吹き飛ばしても、それが記述していたツリーの名前がある限り、情報を失うことはありません。
(特に、まだインスタンス化されていない中間ツリーの表現を持つことができます。
ある意味では、現在のディレクトリキャッシュはツリーコミットへの「作業中」であると考えることができます)。