マインドマップ日記6(分散リポジトリの発展について)

今日のお話は分散リポジトリがどう発展してきたか。センターイメージも枝もないのでマインドマップと呼ぶのは正しくないけどまあこの前のgitマインドマップの続き物なので。

かつてリポジトリってのは1個だけあって、そこにコミットするものだった。黄色円筒がリポジトリ、顔が人でそのそばのはワークツリー。リポジトリとワークツリーの間でchekout/commit/updateする。

この時代「コミット」は二つの行動の抱合せであった。それは「変更履歴の記録」と「変更の公開」だ。複数人での共用リポジトリの場合コミット即公開であった。それが嫌ならばリポジトリをサーバにおかず自分一人で使うことになる。

「変更履歴の記録」のためには、なるべく細かい単位でコミットをした方がいい。その方が各々のチェンジセットの意味が明確になる。しかし「変更の公開」のためには、そのコミットの後でチェックアウトした人のところでビルドが通らないのでは困る。コミットする際には「きちんと動く状態への変更」というある程度大きな塊でなければならない。この二つの目的は衝突する。

ここで「手元のリポジトリ」と「公開用のリポジトリ」の2つがあればいいんじゃないの?って発想が生まれる。リポジトリリポジトリの間のデータのやり取り(clone/push/pull)が生まれる。

リポジトリリポジトリとの間でのやり取りが生まれた。こうなると、そもそも公開用のリポジトリが1個でなきゃいけない理由がないことに気づく。リポジトリが1個しかない状態では変更結果を公開するのにはその中央リポジトリへのコミット権限が必要だ。しかしいっそ各個人が自分の公開用リポジトリを持つようになれば、コミット権がなくても誰でも変更履歴を公開することが出来る。コミッターがオフィシャルのリポジトリに取り込もうと思ったらそこからpullすればいいんだ。

とここまでがいわゆる分散リポジトリの発展の流れだ。しかしgitにはちょっと違う視点の特徴がある。そこが他の分散リポジトリと大きく違っていて、そのせいで混乱が起きるのだと思う。

「変更履歴の記録」と「変更の公開」が切り離された。そして「変更履歴の記録」は細かい単位の方が良い。ならばうっかりワークツリー上でいろいろな変更をやってしまったとしても、それを意味的なまとまりごとに分けて整理してからコミットしたい。整理をするためには整理をするための置き場所が必要だ。「次にコミットする内容」をまとめるための一時置き場が。それがインデックスである。図では処理中の書類を入れておく書類立てをイメージした絵になっている。checkoutは緑矢印なんだけど間違えて赤で描いちゃった。

gitのコマンドをmercurialsubversionのそれと対応付けようと思って混乱していたが、そもそも「コミット」という作業自体が分割されているのである。そこに気付けなかったのが混乱していた理由だった。