ksaitoの日記

日々試したことの覚え書き

Subversionでブランチのマージ

ソースコード管理では基本的に平行開発がないのがベストですが、リリース済みソースの保守作業や大規模な改修では必要なケースもあります。
ここでは、Subversionを使ってブランチのマージに必要な情報を調べたりマージをテストする方法を説明します。

前提

Subversionでは、慣例となっている以下のようなディレクトリ構成を前提に話を進めます。

$ tree sample/
sample/
|-- branches
|   |-- first
|   |   `-- file.txt
|   `-- second
|       `-- file.txt
|-- tags
`-- trunk
    `-- file.txt

trunkから派生したbranches/firstとbranches/secondの2つのブランチで平行開発している想定です。
事前に以下のように環境変数を設定しておくと便利です。

$ echo $REPO
http://svn.local/sandbox/sample
$

ブランチがどのリビジョンから派生しているか確認する方法

svn logに--stop-on-copyオプションを付けるとブランチがコピーされてから最新の修正までのログを表示してくれます。
マージするときに差分の起点となるリビジョンを特定するのに使います。
下記の例では、-vオプションを付けてbranches/firstがリビジョン7から派生されてリビジョン10で変更されていることがわかります。

$ svn log --stop-on-copy -v $REPO/branches/first
------------------------------------------------------------------------
r10 | svn | 2010-01-12 13:06:12 +0900 (火, 12  1月 2010) | 1 line
変更のあったパス:
   M /sample/branches/first/file.txt

update first project.
------------------------------------------------------------------------
r8 | svn | 2010-01-12 13:03:13 +0900 (火, 12  1月 2010) | 2 lines
変更のあったパス:
   A /sample/branches/first (/sample/trunk:7 より)

copy for first project

------------------------------------------------------------------------

URL@リビジョンでリビジョン番号を指定して差分がないことも確認できます。

$ svn diff $REPO/trunk@7 $REPO/branches/first@8
$

trunkへのマージ

それでは、branhces/firstの修正をtrunkにマージします。
先ほど確認したリビジョン8から最新リビジョン(HEAD)までの差分をtrunkに反映します。
マージの流れは、以下の通りです。

  1. trunkのチェックアウト
  2. マージで影響を受けるファイルの確認
  3. ローカルへの差分の反映
  4. 修正箇所の確認(必要に応じてコンフリクトの解決)
  5. コミット

先ほど確認したリビジョンを使ってmergeコマンドに--dry-runオプションを使って影響を受けるファイルを確認します。
--dry-runオプションを付けている場合、ローカルの作業エリアは、変更されません。
下記のようにfile.txtが更新されていることがわかります。

$ svn co $REPO/trunk
A    trunk/file.txt
リビジョン 11 をチェックアウトしました。
$ cd trunk
$ svn merge --dry-run -r 8:HEAD $REPO/branches/first
--- r9 から r11 までを '.' にマージしています:
U    file.txt
$ svn diff
$

あとは、--dry-runオプションを取って実行し作業エリアに変更を反映します。

$ svn merge -r 8:HEAD $REPO/branches/first
--- r9 から r11 までを '.' にマージしています:
U    file.txt
$ svn diff

属性に変更があったパス: .
___________________________________________________________________
追加: svn:mergeinfo
   /sample/branches/first:r9-11 をマージしました

Index: file.txt
===================================================================
--- file.txt	(リビジョン 11)
+++ file.txt	(作業コピー)
@@ -1 +1,2 @@
 This is sample file
+first project.
$

コミット

必要に応じてコンフリクトを解決し、通常通りコミットします。
コメントには、マージしたブランチの名前、リビジョンの起点と終点、マージ先を記録することが推奨されています。
こうした情報は、mergeコマンドが付加してくれても良いような気もしますが...