いくつかのシステムに Mercurial をインストールして使い方を勉強しつつ、なぜ「バージョン管理システムを使うのか」について改めて考えました。
まず「バージョン管理システムはバックアップツールだ」という主張は一見わかりやすいのですが、どうも違和感があるので、さらに考えた末、以前から考えてきたこと(数年前にソフトバンクのCVS本に書いたこと)と重複するのですが
- バージョン管理システムは「無駄なバックアップを安全に消去するツール」である
- バージョン管理システムは「リファクタリングを安全に行うツール」である
と思えてきました。
まず「バックアップの消去」について説明したいと思います。
Windows のユーティリティに undup という重複ファイル削除ソフトがあるらしいのですが、バージョン管理システムは「賢いundup」ではないかと思うのです。
以前と比べてバックアップを取ることは簡単になりました。モバイルPCも安価になり手軽になり、複数のマシンにコピーして作業することも日常的になりました。USBメモリも外付けドライブもネットワークストレージも手軽に使えるようになり、ついあちこちに気軽にバックアップコピーを取ってしまいがちです。
しかし、本当に難しいのは「バックアップを取ること」ではなく「バックアップを捨てること」ではないでしょうか? あちこちにばらまかれてしまった重複ファイルを安全に削除するためにはどうしたらいいでしょうか? 完全に同じファイルなら安全に消すことができますが、もし改変があるなら、それを保存するべきかどうかを簡単に判断できるでしょうか?
消去すべきファイルは、重複ファイルだけではありません。
不要なファイルを簡単に見分けるための工夫として、ここ数年、私はファイル名の付け方の規則として
- 一時ファイルには、先頭文字がアンダースコア(_)で始まるファイル名をつける
ということを教わって実践しています。しかし、いろいろなソフトウェアの事情があり、この規則を徹底できない場合があったとすると、「保存するべきファイルか、一時的なファイルであるか」という区別は、ファイルそのものに記憶させるのではなく、メタ情報として外部に保存する必要が出てきます。
バージョン管理システムのリポジトリとはまず「バックアップをすべきファイルかどうかを表す属性情報である」と捉えてはどうでしょうか。重複ファイルも一時ファイルも簡単に判断できる手段を提供するのがバージョン管理システムだと思うのです。
もう一つの「リファクタリングの道具としてのバージョン管理」については、すでに多くが語られていると思うのですが、「プログラムを、機能を変えずに、構造を改良する」という作業のためには、「確実かつ効率的に過去の状態を参照できる(元の状態に戻せる)」という作業環境が求められます。ファイル群を丸ごとコピーしてしまうと、効率的に差分を表示することが難しくなります。
バックアップとリファクタリングは目的が違います。バックアップは物理的に別のデバイスに保存する必要があるため、ネットワークを介した通信機能は必要です。しかし、リファクタリングはネットワークから切断された状態でも行われるべき作業なので、リポジトリがローカルに存在しないのはとても不便です。
このように考えてみると Mercurial の分散バージョン管理という仕組みは、昨今のコンピュータ利用の現状にふさわしい枠組みではないか、と思います。
ロック・アンロックをベースにしたRCSが大人数での分散作業に向いていない、ということで、コピー・マージ方式を導入したCVSが数年前に広く普及しました。それと同時に「伽藍とバザール」のモデル比較が話題になり、CVSはバザール型のオープンソース開発にふさわしいツールである、と考えられた時代がありました。しかしいま振り返ると、CVSは「バザール開発のツール」というよりも「みんなで分担してひとつの大きなものを作る」ための共同作業ツールであったように思えます。
しかし現実に求められている問題の多くは「みんながそれぞれ自分のための派生物を作る」ことであり、さらに「派生物の差分を取捨選択して共有する」ことだったりします。そのためには、みんなが別々にリポジトリを持つ必要があり、しかもリポジトリ同士でマージを行うメカニズムがやはり必要なのだろう、と思います。