バージョン管理モデル

バージョン管理システムは皆、根本的な問題を解決しなければなりません。それは、どのようにユーザに情報の共有をさせつつ、偶然にも他人の邪魔をしないようにするか、です。リポジトリ内の他の人の変更を、誤って上書きしてしまうことは容易に起こりえます。

ファイル共有の問題

こんなシナリオを考えてみてください。2 人の同僚 Harry と Sally がいます。2 人は同時に同じリポジトリ内のファイルを編集しようとしています。始めに Harry が変更を保存してから、(数分後に) Sally が自分の新しいファイルを偶然にも上書きすることができます。(システムが変更を記憶しているかので) Harry のバージョンが永遠に失われるというわけではありませんが、Harry が行った修正は Sally の新バージョンに隠されて見えません。Sally が Harry の変更を取り込まなかったからです。おそらく偶然ですが、Harry の作業は事実上失われたままです。こういった状況を確実に回避したいのです!

図2.2 回避したい問題

回避したい問題

ロック・変更・アンロック法

多くのバージョンコントロールシステムでは、とても単純な方法である ロック・修正・アンロック モデルでこの問題に取り組んでいます。こういったシステムでは、リポジトリはひとつのファイルにつき同時に一人しか変更できないようにしています。この場合、はじめに Harry は変更を加える前に ロック をしなければなりません。ファイルは貸し出された図書館の本のように、Harry が ファイルにロックをかけると、Sally はそこに変更を加えられなくなります。Sally がファイルをロックしようとしても、リポジトリはその要求を拒否します。できるのは、ファイルを読むことと、Harry が変更を終えてロックを解放するのを待つことだけです。Harry が変更を終えてロックを解放すると Sally はロック・編集できるようになります。

図2.3 ロック・変更・アンロック法

ロック・変更・アンロック法

ロック・修正・アンロックモデルの問題は、少々制限が厳しいことで、しばしばユーザの作業の障害になります。

  • ロックは管理上の問題を起こす可能性があります。 時々 Harry はファイルをロックしたままそれを忘れてしまうことがあります。いっぽう Sally はファイルが編集できるようになるのをずっと待っていて、その間何もできません。Harry が休暇を取ってしまったりすると、Sally は管理者に Harry のロックを解放してもらわなければなりません。この状況では不要な遅れと、時間の浪費が発生します。

  • ロックは不要な直列化を起こす可能性があります。 Harry がテキストファイルの先頭を編集していて、Sally は単に同じファイルの最後を編集したいとしたらどうでしょう? 変更が重なることはありません。簡単にファイルを同時に編集できます。互いを適切にマージできるとすれば、なんの障害も発生しないでしょう。こういった状況ではロックは必要ありません。

  • ロックは誤った安心感を与える可能性があります。 Harry はファイル A をロックして編集し、Sally はファイル B をロックして編集するとします。A と B はお互いに依存しあっている場合、変更すると意味的に矛盾が発生します。突然 A と B がもう一緒には動作しなくなります。ロックするシステムはこの問題に対しては無力です。ある意味、誤った安心感を与えていると言えるでしょう。Harry も Sally もファイルをロックしたことで安全な状態に入ったと感じ、自分の作業は保護されていると錯覚してしまうのです。

コピー・変更・マージ法

Subversion や CVS、その他のバージョンコントロールシステムは、コピー・変更・マージ モデルをロックの代わりに使用します。このモデルではユーザのクライアントごとにリポジトリを読み込み、ファイルやプロジェクトの個人的な作業コピーを作成します。そこからユーザは平行して作業し、個人のコピーを変更します。最後に個人のコピーを新しい最終版にマージします。バージョン管理システムはマージの補助を行いますが、正しくできたかどうかの最終的な責任は人間が負うことになります。

以下に例を挙げます。Harry と Sally はそれぞれ同じプロジェクトの作業コピーを、リポジトリからコピーして作成したとします。2人とも同時に作業し、それぞれのコピーの同じファイル A に変更を加えました。最初に Sally がリポジトリに変更を保存しました。そのあと Harry が変更を適用しようとしましたが、Harry の ファイル A は 最新ではない とリポジトリに言われてしまいました。一方、リポジトリのファイル A には Harry が最後にコピーしたときから何か変更が加わっています。そこで Harry は、リポジトリから新しい変更点を取得し、作業コピーのファイル A に マージ するように指示を出します。おそらく Sally の変更は Harry の変更に重なりません。そのため、いったん両方の変更点を統合してしまえば、作業コピーの内容をリポジトリに書き戻すことができます。

図2.4 コピー・変更・マージ法

コピー・変更・マージ法

図2.5 ...コピー・変更・マージ法 (の続き)

...コピー・変更・マージ法 (の続き)

では、Sally の変更が Harry の変更に重なっていたら? そのときはどうなるのでしょう? この状況は 競合 と呼ばれ、普段はあまり問題になりません。Harry がクライアントプログラムに、リポジトリの最新の変更を自分の作業コピーにマージするよう指示を出すと、作業コピーのファイル A は競合状態としてマークされます。このとき彼は競合した変更を両方とも見ることができ、どちらを選ぶか選択できます。ソフトウェアが自動的に競合を解消できないことに注意してください。理解し正しく選択する力を持っているのは人間だけです。Harry がいったん重なった変更を解消したら、(Sally と競合について話し合ったあとで) マージしたファイルを安全にリポジトリに保存できます。

コピー・変更・マージモデルは少々混沌としているように見えますが、実際にはとてもスムーズに事が進みます。ユーザは他の人を待つこともなく、平行して作業を進められます。同じファイルに対して作業を行った場合でも、ほとんどの変更は重ならないことが判ると思います。そして、競合を解消するのにかかる時間は、ロックシステムで失われる時間よりもずっと少ないのです。

このことは、最終的にひとつの重要な要因にたどり着きます。ユーザ間のコミュニケーションです。ユーザがお互いに意見をやりとりしなければ、構文上・意味上の競合が増えていきます。どんなシステムもユーザに完璧なコミュニケーションを強要できませんし、意味上の競合も検出できません。したがって、ロックシステムなら競合は防げるなどという間違った思い込みで安心するなど、全く意味がありません。実際には、ロックは生産性を下げる以外のなにものでもないように見えます。

ロック・変更・アンロックモデルの方がよいといわれる一般的な状況がひとつあります。マージできないファイルがある場合です。例えば、リポジトリに画像イメージが含まれている場合、2 人の人が同時にイメージを変更してもこれをマージする方法はありません。Harry と Sally、どちらも自分の行った変更を失ってしまいます。

Subversion は何を行うか?

デフォルトで Subversion はコピー・変更・マージ法を使用しますし、ほとんどの場合この方法が常に必要だと思います。しかし、バージョン 1.2 で、Subversion はファイルのロックもサポートしました。したがって、マージできないファイルがあったり、管理するのに単にロックポリシーを強制する場合に、Subversion はそういったお好みの機能を提供することができます。