torutkのブログ

ソフトウェア・エンジニアのブログ

バージョン管理術

開発規模が大きく複数の会社が関わるソフトウェアのバージョン管理をしていると、一筋縄ではいかない問題が多発します。そんなときに、ヒントになりそうな情報をいくつか見かけたのでメモ。

「複数のアジャイルチームでのバージョン管理」

http://www.infoq.com/jp/articles/agile-version-control
InfoQ翻訳記事です。一つのソースコード管理リポジトリに、複数チーム(複数会社)がリリースするような開発体制における効果的なバージョン管理術についてのヒントがあります。

この記事から参照されている文献も読む価値があります。

ベストプラクティス

上述記事から参照されている文献です。

  • ソフトウェア構成管理製品(Preforce)の開発会社が公開している、構成管理の実践記事

http://www.perforce.com/perforce/papers/bestpractices.html

上記の日本語翻訳が、Perforce日本サポート会社東洋テクニカから公開されています。

  • 「ソフトウェア構成管理の高度な実践方法」

http://www.toyo.co.jp/ss/perforce/technical_bestpractice.html

製品固有の話しはまったくないので、ブランチ機能を持った構成管理ツール全般に役立つ記事となっています。

コードライン方針のプレゼン資料

同じく上述記事から参照されている資料です。
http://www.perforce.com/perforce/conferences/us/2005/presentations/Wingerd.pdf

書籍の一部がオンラインで閲覧可能

同じく上述記事から参照されている文献です。オライリーの書籍(洋書)ですが、参照している章はWeb上でPDFで閲覧可能となっています。
http://oreilly.com/catalog/practicalperforce/chapter/ch07.pdf

trunkとbranchの考え方:分散開発

いままでは、バージョン管理を導入するときは、誰でも自由にコミットしてよいtrunkと、試験、リリースなどの安定版を作るタイミングで作成したbranchの2つの「コードライン」だけ想定していました。このモデルで、同一開発場所で作業する10人程度の開発チームのときは、とてもうまく回っていました。


現在関わっているプロジェクトでは、複数の会社がそれぞれの作業場所で開発を行い、会社によっては組み合わせる段階で持ち寄ってくる開発体制となっています。ソースコードの管理は今までどおり、開発中のコードは随時trunkにコミットし、試験・リリース作業を行うときにはbranchを作って作業を行う2段階で考えていました。しかし、以前のように「とてもうまくまわっている」とは言えない状況になりました。

例えば、trunkは必ずしもコンパイルが通らない状況となり、branchは目的を果たして閉じたときに、branch上の修正文がtrunkにマージされていないことがしばしば発生する状況です。


取り決めたインタフェースを変更するとき(要するにシグニチャを変更)、インタフェース提供側と利用側が、同じタイミングで作業できなくなったため、一時的に不整合な期間が発生します。同一開発場所で皆が作業しているときは、この状態は分オーダーで解消できましたが、開発場所が分散している今回は日オーダーでの解消となり、その間、ビルドがエラーとなります。


Subversionを導入した場合、大抵はtrunkにどんどんコミットし、試験やリリースを行う際にbranchを作る方法を取ると思います。しかし、開発人数が増えて、作業場所も分散すると、trunkがビルドできない状態が増え、安定しなくなってきます。branchは安定するのですが、修正をbranchに入れて、あとでtrunkに入れる際、修正数が多くなるとマージがうまくいかないケースが増えて、手直しが頻発します。


ここで、前述の記事で提唱している「メインライン」の考え方を入れると、まずtrunkは「メインライン」として、結合テスト完了版をコミットする場所となります。ポリシーとして従来より制約が強くなります。このままでは、各作業者は自分のPCに結合テストを通していないコードを多く抱えることになるため、ポリシーの緩い開発ブランチを作成します。開発ブランチへは、従来のtrunkと同様のポリシー(コンパイルが通る、またはユニットテストが通る)と同じとします。そして、一つの機能(責務)が完了した時点で開発ブランチからtrunkへリリース(Subversion的にはマージ)するというものです。trunkから開発ブランチには、変更点を頻繁に(朝一番にでも)取り込んでおくのがよいでしょう。


開発ブランチは、会社単位あるいは、開発場所が同じであるグループ単位で用意するのがよさそうです。

上書きコミット問題

開発場所が離れているので、それぞれの開発場所で独自にバージョン管理機構が用意されているようです。このバージョン管理同士は連携していないので、各グループの成果を集める場所にファイル一式を運んできて、その時点で作業コピーをチェックアウト(または単にアップデート)して、そこに運んできたファイル一式を上書きし、続いてコミットする、という「上書きコミット」が発生します。そのファイルにもし第三者による修正が入っていたら、修正自体が消えてしまいます。これを防ぐには、運んできたファイルを置いた後、リポジトリとの差分を見て、意図しない削除や修正があれば、そのままコミットせず、確認して手作業で対処を行う必要があります。これは、同一箇所で開発していない限り不可能なので(ソースファイルの運び人は、すべてのソースの変更を知っているわけではなく、単なるお使い番であったりするので)、何らかのバージョン管理機構による救済が必要ではないかと思っています。

          修正B 
       T0    ↓      T1
trunk ーーーー○ーーー△ーーーー○ーーーーー
              |         ↑
              ↓ 持ち帰り    |持ち込み
開発場所A   ○ーーーーー△ーー○
             ↑
            修正A

・A社がT0時点のソースを開発場所Aに持ち帰り、修正Aを施した
・B社がT0時点とT1時点の間に、A社の持ち帰りソースに修正Bを施し、
 コミットした
・A社がT1時点にソースを持ち込み、そのときtrunkの作業コピーを
 updateしてから上書きしてtrunkにコミットした
・修正Bは失われた
Subversionで上書きコミットを防ぐには
  • T0時点で持ち帰るファイル一式をチェックアウト(またはアップデート)で取り出す
  • T1時点で持ち込んだファイル一式を、T0時点の作業コピー上に上書きする(T1ではダメ)
  • 作業コピーを最新(T1)にアップデートする
  • マージがあれば内容を確認し、コンフリクトがあれば解消し、その後コミットする

となるのですが、作業ルールでカバーするため、間違いのもとです。また、前述のとおり持ち込む人が開発者でないときは、内容確認は難しいでしょう。

分散バージョン管理機構は上書きコミット問題を救えるか?

そこで頭に浮かぶのが、最近流行りの分散バージョン管理システムです。問題の肝は、開発場所が分散しているのにリポジトリが一極集中であるためです。持ち帰りはリポジトリ管理下から引き剥がすことを意味し、持ち込みは新規にリポジトリ管理下へ入れることを作業としてやってしまっているからです。

分散バージョン管理機構ならば、持ち帰るファイル一式をリポジトリのコピーという形で管理下のまま別な開発場所へ移動し、リポジトリに加えられた修正を持ち込み時にもとのリポジトリに反映する、という分散バージョン管理の基本作業に落とし込めます。

今まで、職場での分散バージョン管理導入にはちょっと疑問をもっていましたが、どうやら集中サーバでは扱えない課題のときには威力を発揮する場面がありそうです。

Subversionでも、SVKと呼ぶ分散バージョン管理機構が使えるようですので、検討をしてみたいと思っています。