2014-01-08

Bazaar-NG: 分散バージョン管理システムを7年ハックしてきて

Bazaar-NG: 7 years of hacking on a distributed version control system

Bazaarの開発者が、Bazaarが失敗した理由について、当時を振り返って書いている。なかなか面白い。

Bazaar-NG: 分散バージョン管理システムを7年ハックしてきて

この7年間、筆者はBazaarプロジェクトに関わってきた。筆者はプロジェクトから距離を置き始めている今この時、筆者のこのプロジェクへの関わりや、何が良くて何が悪かったのかの意見などを、振り返ってみるべきだと思う。

この回顧録には多くの複雑な詳細が出てくるので、筆者の誤りもあるかも知れない。間違いを見つけたら知らせてくれ。

黎明期

< ddaa> dscmsには2種類ある。古臭いやつと、実験中なやつ。

2004年、筆者は、 SambaのコントリビューターであるMartin Poolのブログをたまに読んでいた。当時、Martinは異なるバージョン管理システムを調べて、ブログに記していた。筆者も当時、 CVS から Subversionに移行したところで、そこで紹介されている、別の新しいソース管理システムには興味があった、たとえばdarcsやtlaといったものだ。tlaは少し試してみたが、そのモデルは気に入ったものの、実際に使うには面倒すぎると考えた。

2004年末か2005年はじめあたりに、MartinはCanonical Ltd.に入社して、新しい実験的なバージョン管理システム、Bazaarを開発していると発表した。コマンドラインではbazであるBazaarは、GNU archのforkである。

その年の春、筆者は Linux.Conf.Au in Canberraに参加した。MartinはBazaar-NGについてのトークを行った。とうじはそういう名前で呼ばれていて、その場で簡単なデモも行われた。当時のストレージフォーマットは、まだバージョン管理されたファイルの完全なテキストを保持していたので、それほど効率的ではなかった。筆者は単純なUIと分散バージョン管理システムの信頼できる機能が気に入った。そこで、筆者はBazaar-NGを注目しておくリストに付け加え、メーリングリストを眺めた。

LCA 2005における、別の有名なイベントとしては、BitKeeperプロトコルに関する tridgeの悪名高いプレゼンがあった。このトークにより、Larry McVoyはBitKeeperの無料版をやめたし、LinusはGitをハックし始め、Matt MackallはMercurialを始めた。もちろん、当時これを予想できたものは誰一人としていない。

Sambaのbzrの利用

その年の暮れ、SambaははじめてGoogle Summer of Codeに参加した。我々はすべての生徒にSubversionのメインレポジトリへのコミット権を与える管理をしたくなかったので、Bazaarを試してみることに決めた。我々はBazaarにインポートしたソースコードを提供し、生徒たちに、変更を含んだクローンを公開するように言った。

筆者はMartinと知り合いだったし、Bazaar-NGはm当時のDVCSの中ではいい選択だったのだ。すべてのソースコードをSubversionからBazaarに変換するのは大変だった。当時はまだfastexport/fastimportはなかったし、そもそもSubversionからBazaarに変換するためのサポートも一切なかった。ただ、Tailorという、あらゆるVCSからあらゆるVCSへのへんかんをさぽーとしようとしていた ツールがあっただけだ。

Tailorをどう使おうとも、バグは避けられなかった。筆者はいくつかのバグ修正に貢献することになったが、結局信頼できるほど動かすことはできなかった。明らかに欠点は、変換方法であるディスク上のすべての変更を再生にあった。とてつもなく遅かったのだ。

Samba Summer of CodeにBazaarを使うのは、どうみても成功とは言えなかった。とても遅かったし、バグにぶち当たりまくった。明らかに、bzrはSambaのようなサイズのプロジェクトに使うほどには成熟していなかったのだ。筆者はまだ熱中していた。モデルはいいし、bzr開発者はバグ報告への対応が早いし、それに単純でとっつきやすいUIがとても気に入っていたのだ。小さなプロジェクトには筆者は使っていて、とてもよく動いた。

Bazaarは他の分散バージョン管理システムとも組み合わせて使うこともできるが、Subversionとの組み合わせはとりわけてひどく、欠けている部分も多かった。筆者は、この当時、GitのUIがとても基本的で、かろうじてまともに使うためにはラッパースクリプト("cogito")が必要だったことを記憶していている。

最初の貢献

夏過ぎに、筆者は最初のbzrパッチで貢献した。Tailorのソースをいじったことを別にすれば、これが筆者の最初の公開したPythonのコードだ。パッチを受け付けてもらうためには、色々と苦労が必要だった。

その年の暮れ、Gustavoがsvn2bzrの最初のバージョンを公開したので、筆者はテストを開始し、貢献し始めた。svn2bzrの発表に対する私のreplyは、この後、数年にわたって我々が遭遇し続けた問題を的確に言い表している。

sambaレポジトリを変換しようとしたのだけれど、最初の10コミット(~11000コミットのうち)を変換するだけで6時間かかった。tailorだと10時間以内に終わる(メインブランチの6000コミットの変換だけど)

比較のためにいうと、2012年に昔のSambaのSubversionレポジトリの最初の6000のメインラインリビジョンをインポートするのは、5分以内に終わる。

当時を振り返るに、Bazaar-NGは、今よりもずっと、コミュニティプロジェクトだったのだろう。そりゃ、Canonicalは主要な開発者を雇っていたし、ほとんどのファイルにCanonicalのコピーライトはあったが、それよりもずっと多くの人々が貢献していたし、ロードマップはCanonicalの都合ではなく、自由ソフトウェアプロジェクトの需要に従って決められていた。Bazaar-NGは、"bazaar-ng.org"という独自のドメインを持っていた。最初の数年は、貢献者ライセンス同意に署名する必要もなかった。

筆者が興味を持った機能に、Foreign Branchesがあった。Aaronがwikiに書いたように、Bazaar-NGの多数のファイルフォーマットを隠匿する既存の機構は、たとえばSubversionのような、他のバージョン管理システムのフォーマットをサポートするのに使うことができるはずだ。これに触発されて、筆者はBazaarにSubversionを取り込むためのプラグインのハックを始めた。名前は無難にbzr-svnとした。その当時、Sambaは近い将来にSubversionから移行する予定はなかったので、筆者はこれにより、Sambaをbzrからハックできるようになるとも期待していた。

初めてのスプリント

2006年の5月あたりに、LarstiQと筆者は、ロンドンで行われたBazaarのスプリントに招待された。筆者にとっては初めてのスプリントとなる。このスプリントは初めてにして唯一の、Bazaar-Mercurial合同スプリントで、Canonicalのオフィスで行われた。

スプリントには6人参加した。Martin Pool, Robert Collins、John Meinel、Aaron Bentley、Wouter van Heijst、それと筆者だ。この当時、MartinとRobだけがCanonicalで働いていた。他のCanonical社員が遊びに来ることもたまにあった。RobはGNU archのユーザーフレンドリーなforkであるbazにとりかかり、JohnとAaronはtlaとそのforkに、それぞれとりかかった。

スプリントはとても強烈で、部屋に皆で集まると、新しいことが次々と起こるものだ。私自身はそれほど大量のコードを書いたわけではないが、人生であの数日以上に、多くの物事を学んだ日はない。私はエクストリームプログラミングやユニットテストやテスト駆動開発や高度なPythonプログラミングに触れた。あらゆる種類の新しいバージョン管理の概念には、不思議な名前がついていて、まるでX-Filesを見過ぎたような人間が名づけたようだった(ghost rivision、patience diff、history horizon、nuclear launch codesなどなど)

その日の印象は今でも残っている。筆者は小さなホテルの会議室に座って、Robと最初のCommitBuilder APIの実装をペアプログラミングしていた。JohnとWouterがbzrをunicode互換にするためにJohnのどでかいブランチをハックし、最後にしぶとく残るテストを通そうとしていた。Aaronは筆者にrevision id aliasとghostを昼飯を食べながら説明してくれた。小さなCanonicalのオフィスに収まりきらなくなったので、誰かのキッチンテーブルの上に座っていたのを思い出す。David Alloucheは、ホテルのバーでビールをやりながらBazaar-NGの前身とtlaについて筆者に語った。筆者はネストされたツリーについて語った。6年後、われあれは未だに議論している。楽しかった。あのやる気と効率といったら。

あのスプリントの印象は強烈だった。あの時、良き指導者に恵まれなかったら。Martinがスプリントを開催してくれて、Canonicalがスポンサーしてくれて、あの4人のハッカーの辛抱強さには、本当に感謝している。

bazとarchの影響

Bazaar-NGのモデルは、Bazaarの前身(baz)が受け継いだ、archモデルの欠点を埋めることを目的としていた。とはいえ、まだtla/baz/archのレポジトリをインポートして、ユーザーに既存のレポジトリをアップグレードさせることができるはずだった。もともと、Bazaar-NGは次世代のbazのためのPythonで書かれたプロトタイプ的な位置づけだった。モデルの正しさが実証できたならば、baz 2.0として、Cで再実装される予定だったのだ。ある時点で、筆者にも正確には断定できないが、Pythonで書かれたbzr自体が、bazの次世代となることが決定され、既存のbazコードベースは、放置された。

私はArchやBazの利用にあたって不満があったわけではない。ただし、長年、そのモデルについて学ぶにつれて、その欠点も見えてきた。Archはユーザーがリビジョンやディレクトリーやタグに付けられる名前に、かなりの制限を設けていた。学習曲線は急峻で、ユーザーは複雑な内部モデルや、多くの操作用のサブコマンドを熟知しなければならなかった。自分が何をしているかわかっていない場合、自分の足を撃ちぬくのはとても容易で、取り消しできない操作も一部にはあった。誰か他人のブランチから派生する場合に、単に既存のデータをコピーするのではなく、派生先ブランチを歴史としての親ブランチとして参照するようになっていた。もし、他人のレポジトリ(とリビジョン)がネット上から消え失せれば、自分のリビジョンより他の歴史をたどることはできなくなってしまうのだ。

bzr(と既存のArchデータフォーマットの互換性がある部分に関しては、その前身にあたるbazも含めて)はもっとユーザーフレンドリーかつロバストになろうと努力した。ユーザーインターフェースは、馴染み深いCVSやSubversionのコマンドラインに少し近いものになった。リビジョンを内部的に区別する長ったらしい擬似乱数文字列にくわえて、リビジョン番号をユーザーに表示するようにもなった。ほとんどすべての操作はやり直し可能だ。レポジトリはすべてのデータを含むため、歴史へのアクセスは高速で、自分以外の誰かのHTTPサーバーが問題なく稼働しているかどうかに依存する必要もなくなった。WindowsとMacも二級市民ではなくなった。bzrは、UNIX風のスラッシュにくわえて、バックスラッシュもパス区切り文字として認識するようになったし、ファイル名のエンコード方式も規定した。

データフォーマットはデータモデルの結果であり、その逆ではない。データモデルに変更がくわえられたならば、その変更に会うようにファイルフォーマットが変えられる。これは従来のデータベースではとても厄介なことだが、DVCSレポジトリのような分散データベースでは、それほどでもない。

bzrはarchからいくつかの基本的な機能を受け継いだ。ブランチはネット上から消えやすいため、リビジョンも失われることがある。バージョン管理システムはそのことを知っている(なぜならばどこか別の場所へのリファレンスであるから)が、その中身にアクセスすることはできない。これは"ghost rivision"とよばれている。bazではブランチを素のhttpを経由して共有することができた。bazにおけるリビジョンとファイルはユニークな識別子が振られていて、名前が変えられたとしても、その正体を追うことができる。bzrはリビジョンIDとファイルIDという概念は保持したが、その制約を変えた。IDを単に擬似乱数文字列としたのだ。目的はgitがやっているような「おバカ」な中身のトラッキングではなく、正体のトラッキングだ。

これらの機能はとてもいいものなのだが、果たして苦労に見合うだけの利点があったかどうか疑問だ。どうも思うに、bzrは人々がarchやそのforkに対して思いつくあらゆる機能をサポートすべきだ、ひとつのDVCSはすべてを統べる、といった感じの風潮があったのではないか。一部の機能がどのくらい役立つかは、当時としても疑問だった。

筆者はghost revisionの熱烈な支持者であった。ghost revisionは別のフォーマットをサポートするのにとても便利だったからだ。しかし、パフォーマンスに悪影響を与え、fetch操作における失われたリビジョンを見つけるアルゴリズムも複雑になった。また、我々は、オホン、幽霊と相いれぬ多くのバグに悩まされてきた。bazからのインポートさえなければ、ゴーストのサポートは、もう少し後まで遅らせるべきだったのだ。

愚直な転送のサポート。ブランチの提供元にbzr専用のコードを必要とせず、HTTPやFTP経由でアクセスできることは、とてもいい機能だ。この利点としては、通常のHTTPやFTPサーバーを開発ブランチのホストに使えるということだ。特に、クラウド以前の時代には、CVSやSubversionのように、独自のコードをサーバー上で動かす必要があることに比べて、とても大きな利点だった。

Bazaarの転送の隠匿により、同じコードがローカルレポジトリにもリモートレポジトリにも利用できた。bzr logをフルクローンせずにリモートレポジトリに対して走らせることができるのは感動だ。このような方法で愚直な転送をサポートするには、ツケも支払わなければならなかった。HTTP越しのパフォーマンスに影響するため、レポジトリへのアクセスは、あまりシークできないし、巨大なデータを読み込むこともできなかった。

だが、その代わりに、リモートレポジトリにもあらゆる操作ができるのだ。ただ、ユーザーがフェッチしてローカルで自前で行うのではなく、レポジトリとブランチに対するすべての操作をサーバー側で行うbzrスマートサーバーを実装するときには、これは問題になったのだが。

bazにあった素晴らしい機能が、パフォーマンス上の理由で捨てられたものもある。cherry-pick merge trackingのサポートだ。

(Some of Martin's early notes on Arch).

当初、Bazaarのリリースは頻繁だった。しばらく、月齢リリースがあった。三週間の開発と一週間の安定化とプラグイン修正だ。開発は小刻みで、すぐに採用された。ファイルフォーマットや設定にほんのわずかでも、以前のバージョンのbzrが読み込めない可能性がある極小の新機能が追加されたツォいても、ファイルフォーマットバージョンがインクリメントされた。変更は積み重ねるのではなく、即座に適用したのだ。これにより、数ヶ月おきに新しいフォーマットが出ることになった。その後、フォーマットの変更は収まり、2009年からは、新しいフォーマットは追加されていない。残念ながら、bzrは二週間おきに新しいファイルフォーマットを追加しやがるぜ、というイメージを払拭させることはできなかった。

オーガ

筆者が参加していたもうひとつのプロジェクトは、「オーガモデル」と呼ばれていた。なぜならば、オーガのように、そしてソフトウェアとしては珍しく、レイヤーを持っていたからだ。

Bazaarが新しいバージョンのファイルフォーマットをこれほど頻繁に追加できた理由は、UIと、APIと、ファイルフォーマットの実装が、綺麗に隠匿されているからだ。これはgitとはえらい違いだ。gitはディスク上の様々なものをUIに露出させている(例えば、ディスク上のリビジョンを識別するためのsha1チェックサムだとか)。既存のgitのツールを、全く別のファイルフォーマットに対応させるのはとてもむずかしい。Bazaarにとっては、とても簡単だ。

思うに、この点こそが、どちらも似たようなモデルを使っているBazaarとGitの重要な違いなのだろう。このために、Bazaarは昔の日効率的なweave formatからpack formatに簡単に移行できたわけだし、別のフォーマットも第一級市民としてサポートできるが、大量のグルーコードや余計な複雑さがついてまわる。様々な点で、Bazaarはトップダウンに作られているのだ。Gitのようなボトムアップとは違う。

ただし、これはBazaarがGitより優れていると主張しているのではない。David Wheelerかだれかが言ったはずだが、

All problems in computer science can be solved by another level of indirection... Except for the problem of too many layers of indirection.

コンピューター科学におけるあらゆる問題は、さらに一段階の間接参照を挟んでやれば解決できる。ただし、あまりに間接参照のレイヤーが重なり過ぎるという問題だけは解決できない。

パッチの採用が困難

Bazaarは変更に対してかなり厳しい要件を設けていた。これは良くもあり悪くもある。すべてのバグフィクスや挙動の変更は、テストスイートにも変更を反映させたり、あるいはテストスイートを拡張したりする必要がある。すべての変更は、二人のコミッターによってレビューされる必要がある(ただし、コミッターはセルフレビューできるので、あと一人だけでもいい)。CanonicalがBazaarのほとんどのソースコードの著作権を保有する(歴史的な理由による例外もある)。それから、2009年からは、Canonicalのcontributor license agreementに署名する必要もでてきた。

筆者の初めてのパッチが採用されるには相当に時間がかかった。修正自体は簡単だったのだが、適合するテストを書くのは難しかった。たまに現れる貢献者も、この問題と格闘していたし、実際、何人かには貢献を避けるだけのものがあった。やがて、CanonicalのBazaarハッカー達は貢献者からのパッチを代行するようになったので、バグ修正や変更が採用されるのが、だいぶ簡単になった。

もちろん、れびゅーとテストにここまで厳格であることで得られる恩恵もあった。採用されるほとんどの変更は高品質だった。テスト、リファクタ、その他の些細な変更が自身を持って行えた。筆者はBazaarに大きなデータロスのようなバグを見たことがない。regressionは起こるには起こったがまれだった(プラグインの互換性を壊すAPIの変更は別だが)。筆者は何年も、bzrのtrunkを快適に使っていた。

ただ、品質要求が貢献者を遠ざけたわけではないと思う。GitやMercurialにしても、そこまで厳格ではないかも知れないが、似たような要件を課していただろう。彼らとて、そのために行われなかった貢献もあったはずだ。

あるいは、Bazaarがよそに比べて複雑なところが、貢献の大小のちがいなのだろうか。ほとんどのGitユーザーはファイルフォーマットの詳細を知っているし、たとえ知らないにせよ一日で学べる。Gitのバグをソースファイル上で見つけるのは、様々なレイヤーが関係するBazaarを理解するよりも、だいぶ簡単だ。新し目のBazaarのファイルフォーマットは、たいていドキュメント化されていない。bzrの世界にいて何年も経た後でも、いまだに筆者は、gitのpack実装のバグを修正するほうが、Bazaarのバグを修正するより簡単だと感じる。

あるいは、違いを如実に語る例として、Gitの詳細のLWN記事が、Gitのリリースから5日後に公開されたことが挙げられるだろうか。

これはファイルフォーマットについて知りたい一部のギークどもが臆病風にふれられて逃げ出すから問題というわけではない。ユーザーが何か低級層のコードの問題に出くわした時、その問題を修正するだけの力がないことが問題なのだ。ユーザーがbzrのバグに出くわして、レポジトリにアクセスできなくなり、悪態をつきながら離れていったのをみるとき、とても残念に思う。そのバグがどんなに些細なものであったにせよ。

プラグイン

Bazaarの良くも悪くもある別の点としては、プラグインだ。bzrlibのほぼすべての箇所は、プラグインで拡張可能だ。Bazaarを変更するプラグインで最も多い利用方法は、新しいサブコマンドの追加だ。プラグインがインストールされれば、常にbzrlibに読み込まれて初期化されるのだ。

Pythonを少しかじっていればプラグインを書ける。いいドキュメントが揃っているし、基礎的なプラグインを書くのには、bzrの詳細についてそれほど知っている必要はない。プラグインではほとんど何でもできる。例えばレポジトリのファイルフォーマットのサポートだとか、bzr logの出力フォーマットのオーバーライドだとか、レポジトリにアクセスできるプロトコルの追加だとか。

ある意味、プラグインはbzr本体に新しいコードが採用されにくい状況への対象方法として使われていたのだ。わざわざレビューワーを説得する必要もない。テストを書く必要もない。要するに、プレグインは新しい機能を試すのに最適だったということだ。Canonicalへの著作権譲渡も必要ない。

プラグインはBazaar本体より遅れていることが多かった。APIに対する変更は、そのAPIを使うプラグインをぶち壊してしまう。古いAPIを非推奨扱いにして、ユーザーに新しいものを使うように促す機構も用意されていた。ただし、bzrlibには大量の公開されたAPIがあったのだ。現実には、プラグインで使うのはその一部で、公式な方法で非推奨扱いにするのは時間がかかったので、しばしば見送られた。

新機能をプラグインに突っ込むのがとても簡単であるがために、変更を上流に採用させるためのインセンティブに欠けていた。実際、これにより、インストールされたBazaarを最新版に保つというのは、Bazaarバージョンとプラグインのバージョンをジャグリングしているようなものだ。お互いに互換性がなければならないのだ。

我々はBazaar自体にもっとプラグインを盛り込むべきだったのだ。Pythonのように、バッテリーまでついてます[訳注: batteries includedとは、Pythonの標準ライブラリがとても充実している様を言い表す慣用句]とね。MercurialもGitもやっていたことだ。

急速な開発

2005年から、CanonicalのBazaar部署はゆっくりと5人にまで増えていった。2006年と2007年は、新しい楽しい変更が常にあった。スプリントももっとあったし、筆者もさらに大勢のbzrの貢献者に対面した。Andrew Bennetts, Vincent Ladeuil, Ian Clatworthy, Martin Albisetti。

Bazaarはファイルフォーマットをとても改良した。そしてさらにpackファイルに入れるためにも変更した。高パフォーマンスのスマートサーバーも入ったが、ただし、「高パフォーマンス」という部分は、当時はやや理論的なところがあった。我々はシリアライズされたリビジョン(バンドル)をメールで送りあった。Bazaarのグラフィカルなフロントエンドを作る人や、Webフロントエンドを作る人も出てきた。

Bazaar開発の議論は、ほとんどIRCかメーリングリストで行われていた。変更を提案するには、パッチか、マージリクエストをメーリングリストに送る。するとコミッターがレビューして、メインのBazaarブランチを管理するBOTに送る。やがて、Aaron BentleyがBundleBuggyというWebサイトを立ち上げたので、メーリングリストに提出された変更とその状態をトラックすることができるようになった。

大移行

2007年の終わり頃、最初の大き目の自由ソフトウェアプロジェクトが分散バージョン管理に目をつけ始めた。2008年から2009年にかけて、大量のプロジェクトが中央バージョン管理から移行してきた。

前回のVCS移行、すなわちCVSからSubversionからの移行は、Sambaではとてもうまくいった。2007年10月に、ある開発者が、Gitへの移行を提案した。筆者はSambaに貢献するために、bzr-svnを長年使っていて、GitのかわりにBazaarを提案したかったが、パフォーマンスという点で、まだGitには遠く及ばないと気がついた。Sambaが移行した後、筆者はbzr-gitをハックし、Bazaarを使い続けられるようにした。

2008年1月、BazaarはGNUプロジェクトになった。現実に、特に何かが変わったというわけではなかった。

2008年、さらに多くのプロジェクトが、三大分散バージョン管理システムに移行し始めた、Mercurial、Git、Bazaarだ。筆者はまだforeign branchプラグインや、bzr-gitや、Robが始めたbzr-hgプラグインに関わっていたし、さらにbzr-svnや、 bzr-gtkにも関わっていた。

さて、Launchpadはマージの提案をまともにサポートしたので、BazaarはLaunchpadに移行して、メーリングリストに送られたbundleに変わって、Launchpadを使ってマージの提案を行うようになった。

一方、DVCSツールもだいぶ発達してきた。多くの人が、Visual StudioやEclipseやNautilusにDVCSを組み込みはじめた。Ian Clatworthyはドキュメントをまともに整備し、bzr-explorerを始めた。CanonicalのBazaarチームは、Bazaarに移行したい様々なプロジェクトからの要望に答えるべく働いた。

筆者は、様々な外部ツールとの連携が十分にとれていないことが、ユーザーからとっつきにくくしているのではないかと危惧していた。当時を振り返るに、おそらく筆者は、原因と結果を取り違えていたのだろう。

改変不可能性と、完全な歴史

Bazaarは、それ以前にあったArchやSubversionのように、歴史を忠実に記録することに力を注いでいた。歴史は参照されるが失われることもある(ghost rivision)。理由は単になくなったか、あるいは誰かが意図的にレポジトリから消したか(たとえば、誤ってパスワードをコミットしてしまったとか)

Bazaar開発者は常に、歴史の改変は邪道であると考えていた。歴史が正確ではなくなるという以外の、改変可能な歴史に対する反論としては、歴史を改変させることを許してしまうと、ユーザーが容易に自分の足を撃ち抜けるようになってしまうからだ。歴史の改変は、同じデータに対する2つの微妙に異なるバージョンを生み出す。このような改変を拡散させるのは、関わりたくないほどに難しくなる。

当初の計画では、Bazaarにアノテーションをつける予定だった。Gitでオブジェクトにノートを付与して、コミットメッセージの誤字脱字を修正できるのと同じだ。

その他のBazaarの設計思想としては、後で必要となる場合に備えて、可能な限りの情報を保持するということだ。Bazaarは明示的に、リネームを記録しているし、たとえば、一連の変更点を提出させるときなどに、歴史を組み込むことを推奨している。

パッチのためにユーザーの歴史を破棄するのではなく、変更をもたらす新しい"mainline"コミットとして参照される。

"mainline"とは、左手側の祖先である、いうなれば、tip(ノードの最初の親)からDAGの左手側に潜っていって、ツリーの根本まで戻っていったときにみるリビジョンだ。

BazaarのUIはmainlineの概念を反映している。たとえば、ドットなしのリビジョン番号はmainlineのリビジョンで、"bzr log"と"bzr qlog"は、デフォルトでmainlineしか表示しない。貢献者がパッチを提出する前の変更点である右手側の歴史は、本当に必要とするときのために記録されているが、通常は隠されている。

この時点で、多くのプロジェクトが、既存の歴史を、次世代DVCSにインポートしてテストしようとしていた。Git、Mercurial、BazaarメーリングリストとIRCチャンネルは、どのシステムが、他のシステムには存在する必要不可欠な機能を欠いているかという議論とフレーム戦争であふれかえっていた。多くのプロジェクトが、それぞれ思い思いにピカピカの次世代ソースコード管理ツールを選んでいくに連れ、bzrの問題点が、次第に明らかになってきた。

パフォーマンス

長年、パフォーマンスは次第次第に向上してはいたものの、Bazaarはまだ、中規模から大規模のプロジェクトで、十分な速度ではなかった。プロジェクトは、Bazaarを使うと、Gitやmercurialを使った時に比べて、より多くのディスク容量を必要とした。

運用

Bazaarが提供しているいくつもの運用は、人々を混乱させた。bzrは、独立したブランチからお互いにpullしたりpushしたりといった真の分散型として使うこともできれば、SubversionやCVSのような、中央環境でやるような、中央ブランチに束縛されたローカルブランチとして使うこともできた。Bazaarの主要な開発者は中央管理的な運用をすることはなかったので、これはやや特殊な用法だが。

一つのブランチにつきひとつのディレクトリという方針は、小規模なプロジェクトにはうまく動くが、レポジトリのサイズが増大するにつれて破綻した。ユーザーはディスク効率のため、複数のブランチから共有されるレポジトリの作成を余儀なくされた。Cプロジェクトではたいてい、同じworking treeを複数のブランチで再利用するのは便利なことだ。これはBazaarでも可能なのだが、それほど便利ではなかった。

ヒストリートラッキング VS コンテンツトラッキング

History is a set of lies agreed upon.

歴史とは、合意された嘘の集合である。

Bazaarの思想の3つ目の問題は、完全に改変不可能な歴史である。ソフトウェア開発者は歴史家でも法律家でもない。多くのユーザーは、歴史を簡単にしておきたいと思うものだ。ユーザーが気にかけるのは、trunkに起こった変更を追って、変更の経緯を明らかにすることであって、trunkに入るに至ったパッチに対する個々のコミットや間違いではない。Gitは"rebase"を提供してる。これは、単に上流ツリーにローカルの変更を再適用するものだ。Gitはしばしば、バージョン管理ツールではなく、コンテンツトラッカーと呼ばれている。そういう名前で呼ばれたほうが理解しやすいのだ。

これに関係するが、Gitは単純なコマンドラインツールによって、レポジトリを低級層からひっかきまわすことができる。例えば、SVNからインポートされたレポジトリから、巨大なISOを除外することができる。Bazaarは長年、rebaseプラグインはなかったし、ようやくrebaseプラグインが出てきた時も、パフォーマンスが遅すぎたし、あまり強力ではなかった。Bazaarには、必要とあらば変な歴史を改変するためのツールは、あまりなかったのだ。

当時、筆者が少し驚いたことには、多くの人は、Gitのリネームの検出が100%の精度をもっていないことを、あまり気にしていないことだった。どうやら、リネームの誤検出に出くわすのは、それほど頻繁ではなかった(それに簡単に対処できる)ようなので、十分にやっていけたようだ。筆者もやっていけたし、問題に出くわしたのは、数えるほどしかなかった。

Bazaarのリネームに対する解決方法にも問題はあった。Bazaarはユニークな識別子を、ファイルが最初にワーキングツリーに追加される際に割り当て、ファイル名が変更されたとしても、ファイルをトラックしていた。これはファイルが独立してバージョン管理され、ユニーク識別子が2つある場合に、とても問題になった。

技術的に、BazaarとGitのデータモデルは、それほど違ってはいないというのは、興味深い点だ。Bazaarは明示的にディレクトリをトラックし、ファイルにIDを付与してリネームもトラックしていた。一方、Gitはヒューリスティックを使った。違いはむしろ思想や、ツールや、ディスクのレイアウトだ。

CanonicalのBazaar人員は、パフォーマンスの問題と、レポジトリのディスク上のサイズを解決するために、新しいフォーマットを設計した。brisbane-cre (2a)は2009年の夏頃に公開された。ただし、バグもかなりあった。特定の利用例でのパフォーマンスregressionもあった。残念なことに、この時点で、Bazaarは遅いものだという評判が定着していたため、光のように速い新フォーマットでも、揺さぶりをかけることはできなかった。

一部の人間は、Bazaarはそれほどコミュニティによる貢献がなく、完全にCanonicalの塀の中で開発されたと主張する。皮肉なものだ。Bazaarの大部分はCanonical社員に寄って書かれたことは確かだが、それはCanonicalがBazaarに貢献していた人間を雇ったからにすぎないのだ。多くの者は、Canonicalのその他のコードの開発に移っていった。

筆者も、2009年にCanonicalに入社して、Lunchpadのパッケージ側(Soyuz)の開発を、AGPLでリリースされた数カ月後から行っていた。筆者は暇な時間にBazaarの開発をしていた。

利用者減少とUbuntuへの注力とUDD

2009年の終わり頃、GitがDVCS戦争の商社となりつつあることは次第に明らかになっていった。Bazaarへのコミュニティの貢献は次第に減っていったのだ。

2009年末、CanonicalはBazaar業界に姿を現し始めた。Canonicalは商用サポートを売りはじめ、同時に、オンラインにパッチを提出した貢献者は、まず contributor agreementに署名するよう求められた。2010年のどこかで、ドメイン名がbazaar-vcs.orgから、bazaar.canonical.comに変わった。

CanonicalのBazaarチームの目的は、BazaarがUbuntuプロジェクトのパッケージ管理をうまく扱える、まともな汎用のバージョン管理システムとすることになった。CanonicalにおけるBazaarの当初の目的は、すべてのソースパッケージに使えることにより、未だにtarballとdiffに固執するUbuntu開発者に、バージョン管理の利点をもたらすことだった。

筆者はBazaarの人気のなさに失望していたものの、まだBazaarには期待していたし、Ubuntuのソースコードの管理ツールとなるという役割をはたすことにも期待していた。foreign branchのサポートは、世の中にいくつもあるVCSツールを、共通のインターフェースで扱えるという点で、重要だと考えていた。筆者はLaunchpadのテクニカルアーキテクトになったRobのかわりに、Bazaarチームに移った

James Westbyは、bzr-builddebプラグインを土台にして、すべてのUbuntuのソースパッケージをBazaarに自動的にインポートするスクリプトを書いた。Bazaarチームは、Jamesの実験的な実装を引き継いで、1万7千ほどあるすべてのUbuntuのソースパッケージを、Bazaarにインポートすることを試みた。すべてのパッケージに適用することができた暁には、Launchpadのtarballアップロードは無効化され、Launchpadにブランチをpushするという新しいアップロード方法になるはずだった。

問題なくすべてのパッケージをインポートするということは、とてもむずかしい問題であった。ヘンテコなファイル名のパッケージあり(UTF-8ではない文字や、バックスラッシュや改行)、奇妙な祖先あり(Debianからの変更をマージ、nativeからregularに変更してさらに戻すなど)、とてもでかいファイルあり、debianの複数のtarballあり、他にもあらゆる奇妙なものであふれかえっていた。

長い間、癌と闘病してきた末に、 Ianが亡くなった。Ianはbzr-explorerのドキュメントに尽力してきたし、それ以上に、陽気で、とてもいい奴だった。

パッケージブランチが古くなったことに伴うfetchが、古き良きtarball(これは広くミラーされている)より遅いとあっては、Ubuntu開発者から、あまりいい目でみられなかった。当時を振り返るに、すべてのパッケージをBazaarに移行する前に、すべてのパッケージをBazaarに正しくインポートするというのは、間違っていたのだろう。パッケージを一つづつBazaarに移行させていくほうが良かったのだろう。そもそも、Ubuntuにとって重要なパッケージは限られているわけだし、パッケージインポーターを正しく動かすという難しい作業も省ける。

負け組Bazaar

CanonicalのBazaarチーム以外の外部の人間による貢献は、2011年の半ば辺りには、まれになってしまった。2012年の初頭には、CanonicalのBazaarチームは他のプロジェクトに配置転換されてしまった。まだ、たまにBazaarのバグフィクスぐらいはするのだが。Martinは2012年4月にCanonicalを退職した

2012年の前半6ヶ月、筆者は暇な時間で、作業中のブランチを完成させた。その後は、なるがままに任せようと考えた。

そろそろ、先に進むべき時だろう。まだ気に入らない部分もあるにせよ、Gitはまともなソースコード管理システムだ。Bazaarは、これ以上発展しない。数年後にも新しいユーザーは出るだろうし、バグ修正の貢献者もいるだろうが、筆者が願っていたほど広く受け入れられてはいないのだ。

bzrはGitファイルフォーマットへの別のUIとして、つまり、Gitと競合するのではなく、Gitの一部として、第二の人生を歩むことができるだろうか? まあ、できるかもしれない。筆者も含む何人かは、そういう提案もしていた。そうするとしても、まだやるべき作業が多すぎる。bzr-gitは未完成なのだ。Bazaarが単にUIだとするならば、bzr風のGit UIをスクラッチから、libgit2とかDulwichとかの上にでも作ったほうがいいだろう。

結論

Bazaarにはもっと可能性があった。Bazaarは人気で書きやすいプログラミング言語で書かれていた。コードは綺麗で、コメントも大量にあり、テストのカバー率も高かった。Bazaarには簡単なコマンドラインUIがあり、ナイスなグラフィカルフロントエンドがあり、まともなクロスプラットフォームのサポートもあり、十分にドキュメント化されていた。何年もの間、フルタイムのエンジニアが働いていて、活発なコミュニティも存在した。

我々には、大切なものがわかっていなかったのだ。いい機能だけれど、思ったほどには必須ではない機能に注力してしまった。あまりにもやりすぎてしまった。無意味に込み入った不必要な機能を削ぎ落とさなかった。理解が難しく、貢献が難しく、巨大なレイヤー化されたコードベースのパフォーマンスの修正も難しかった。コードベースが大きくなるに連れ、バグの範囲も広くなり、リファクターも難しくなっていった。

これは筆者の専門である、foreign branchプラグインにも言えることだ。bzr logやbzr diff -c 1200やBazaarの標準APIが、GitからBazaarへのレポジトリの変換を介さずに、Gitレポジトリを直接扱えるのは、便利であるのは確かだ。しかし、そのために余計に複雑になり、余計にアーキテクチャー上の(パフォーマンスの)バグを出してまで、価値のあるものだっただろうか?

Bazaarを、いい奴、才能のある奴と開発できたのは楽しかった。筆者はとんでもなく多くを学べた。何か、新しいことを始めるべき時だ。

No comments: