複数の開発者が作成したコードをマージしたり、仕様が一部異なる複数のプロジェクトに共通の変更を加えたりするときに、手間なく正確に作業するにはバージョン管理システムが役に立ちます。数年前からバージョン管理システムのSubversion(TortoiseSVN)を使ってきましたが、今回Mercirual(TortoiseHg)を試しました。
リポジトリ・コミット・マージ
変更履歴を記録してあるデータストアをリポジトリと呼びます。コミットでその時点のスナップショットをリポジトリに保存します。このときリビジョンが刻まれ、必要があれば簡単に任意のリビジョンに戻すことができます。
バージョン管理で重要な機能がマージです。マージは複数箇所での変更を1つのまとめる機能です。異なる開発者の変更をまとめるときや、あるプロジェクトに加えた変更を仕様が一部異なる別のプロジェクトに適用するときにマージが発生します。ファイルをプロジェクトに追加しても自動的にマージしてくれるのはもちろんのこと、同じファイルを変更した場合にも変更を加えた行が隣り合っていなければ自動でマージしてくれます。隣り合っているか同一行を変更した場合は競合が発生し、競合解消用のエディタによって手動でマージします。
集中型・分散型
Subversionはリポジトリを1カ所で持つ集中型と呼ばれる物で、それに対してMercirualはリポジトリを複数持つことができる分散型と呼ばれる物です。開発者それぞれがコーディングのスクラップアンドビルドするときに自分用のリポジトリを利用すれば他の開発者に影響を与えません。これが分散型のメリットです。Mercurialの他にGit、Bazaarなどがあります。
当方は開発規模が小さいので集中型のSubversionでも十分なのですが、Mercurialに備わっているRebase, Transplant, Splitが仕様が一部異なる複数のプロジェクトを管理するのに便利に使えることがわかりました。
ブランチ
一部仕様の異なる複数のプロジェクトはブランチという機能を使って管理します。メインで開発するブランチをSubversionではtrunkという名前を付ける習慣になっているようです。trunkでの変更を別のブランチにも適用するとき、Subversionではリビジョンの範囲をマージという機能を使います。更新→マージ→動作確認→コミットの順で操作します。どこまでのリビジョンをブランチに適用したかSubversionが把握してくれているので、いちいちマージするリビジョンを指定する必要はありません。ブランチで変更した結果をtrunkに反映する際にもリビジョンの範囲をマージを使います。但し、相互にマージする場合は、相手方のブランチでの変更だけをマージするためリビジョンの範囲を明示的に指定します。マージ結果をコミットしたリビジョンまでマージしてしまうと同じ更新を2度コミットすることになり、競合が発生します。
リビジョンの範囲をマージを使うと2つのブランチがそれぞれの更新を他方のブランチにマージする形でリビジョンが成長していきます。
Mercurial
MercurialのRebaseはこれとはことなりブランチの分岐点を変えることによって共通の変更を他のブランチに適用します。つまりdefault(Subversionのtrunkに相当)とブランチの差違を最後に適用したことにできるのです。逆にブランチに加えた変更をdefaultに適用するときはTransplantによってdefaultに適用したことにして、Splitによってブランチに適用した変更を取り消し、Rebaseします。
リビジョンの成長過程はリビジョングラフによって確認できますが、リビジョングラフがシンプルでわかりやすいものになり、私はこの方法が気に入りました。
Mercurialは日本語ファイル名の扱いに難があり、win32mbcsエクステンションを使用し、一部のDLLを入れ替えなければなりません。
私は下記URLを参考に設定しました。
http://www.asukaze.net/etc/vcs/hg-fixutf8.html
しかし、Transplant実行時に日本語ファイル名が原因でエラーが出てしまいました。当初想定した使い方ができないので今のところSubVersionを継続使用するつもりです。
mercurial 2.0 では上記の不具合が解消されているようです。win32mbcsエクステンションは必要ですがDLLの入れ替えは不要になっているようです。時間を掛けて検証していないので見落としがある可能性があります。次回新たなプロジェクトが立ち上がったら使ってみます。
Git
久しぶりに見返しましたが、この記事を書いたときから状況が変わりました。Visual Studio にも最初から Git がついています。現在ではもっぱら Git を使用しています。