連絡先 トップに戻る 最初に戻る 前に戻る 次に進む
$Date: 2017-05-06 22:21:48 +0900 (2017/05/06 (土)) $
$Revision: 1117 $

特定のリビジョンだけマージ(Cherry Picking)

概要

trunk で行った修正を特定のリビジョンの修正だけリリースブランチに反映したい場合など リビジョンを指定して行うマージを、Cherry Picking と呼びます。

Subversion 1.5 では Merge Tracking 機能をサポートしています。 Subversion は、マージ元 URL とマージ済みリビジョンを記録します。 次にマージするときに同じ修正を再度マージしようとしても自動的にマージ対象から除外します。 Subversion が行うのは、記録した情報を元に単に特定のリビジョンを含めるかあるいは含めないか の判断のみ行います。

Subversion 1.5 では マージしていない修正のすべてをマージするときに特定のリビジョンだけマージしない ように、マージしないリビジョンを指定することはできません。つまり svnmerge.py block の 機能は実装していません。 たぶん Subversion 1.6 でサポートされると思います。

操作方法

マージするためには svn merge コマンドを使います。これは Subversion 1.4 以前と同じです。 違うのは svn merge コマンドでマージしたときに svn:mergeinfo というプロパティでどの リビジョンをマージしたかを Subversion が自動的に記録して、2 回同じ修正をマージしない ように保証してくれるという点です。

具体例

コマンドは こちら

処理の流れ

  1. [準備] リポジトリ作成
  2. [準備] trunk を修正
  3. [準備] ブランチを作成
  4. [準備] trunk を修正
  5. リビジョン4 を trunk → ブランチ 1.0.x にマージする
  6. マージ情報の確認
  7. 再度、リビジョン4 を trunk → ブランチ 1.0.x にマージしてみる

-c オプションは -r の省略表現です。
例えば -c 4 とすると -r 3:4 と同じ意味です。 また -c -4 というように負のリビジョンを指定すると -r 4:3 と同じ意味です。 svn merge で指定すると逆マージを指します。

[準備] リポジトリ作成

D:\tmp>cd /d D:\tmp

D:\tmp>svnadmin create repos

D:\tmp>svn co file:///D:/tmp/repos work
リビジョン 0 をチェックアウトしました。

D:\tmp>
D:\tmp>cd work

D:\tmp\work>svn mkdir tags branches trunk
A         tags
A         branches
A         trunk

D:\tmp\work>svn ci -m "initial dir"
追加しています              branches
追加しています              tags
追加しています              trunk

リビジョン 1 をコミットしました。

[準備] trunk を修正

D:\tmp\work>cd /d D:\tmp

D:\tmp>svn co  file:///D:/tmp/repos/trunk
リビジョン 1 をチェックアウトしました。

D:\tmp>cd trunk

D:\tmp\trunk>echo 1 > test.txt

D:\tmp\trunk>svn add test.txt
A         test.txt

D:\tmp\trunk>svn ci -m "add test.txt"
追加しています              test.txt
ファイルのデータを送信しています .
リビジョン 2 をコミットしました。

[準備] ブランチを作成

D:\tmp\trunk>svn cp  file:///D:/tmp/repos/trunk  file:///D:/tmp/repos/branches/1.0.x -m "make 1.0.x branc"

リビジョン 3 をコミットしました。

[準備] trunk を修正

D:\tmp\trunk>echo 2 >> test.txt

D:\tmp\trunk>svn ci -m "fix bug"
送信しています              test.txt
ファイルのデータを送信しています .
リビジョン 4 をコミットしました。

D:\tmp\trunk>echo 3 >> test.txt

D:\tmp\trunk>svn ci -m "fix bug 2"
送信しています              test.txt
ファイルのデータを送信しています .
リビジョン 5 をコミットしました。

リビジョン4 を trunk → ブランチ 1.0.x にマージする

D:\tmp\trunk>cd /d D:\tmp

D:\tmp>svn co  file:///D:/tmp/repos/branches/1.0.x
A    1.0.x\test.txt
リビジョン 5 をチェックアウトしました。

D:\tmp>
D:\tmp>cd 1.0.x

D:\tmp\1.0.x>svn merge -c 4 file:///D:/tmp/repos/trunk
--- r4 を '.' にマージしています:
U    test.txt

D:\tmp\1.0.x>svn di

属性に変更があったパス: .
___________________________________________________________________
追加: svn:mergeinfo
   /trunk:r4 をマージしました

Index: test.txt
===================================================================
--- test.txt    (リビジョン 5)
+++ test.txt    (作業コピー)
@@ -1 +1,2 @@
 1
+2

D:\tmp\1.0.x>svn ci -m "merge from trunk"
送信しています              .
送信しています              test.txt
ファイルのデータを送信しています .
リビジョン 6 をコミットしました。

マージ情報の確認

D:\tmp\1.0.x>svn up
リビジョン 6 です。

D:\tmp\1.0.x>svn pg svn:mergeinfo file:///D:/tmp/repos/branches/1.0.x
/trunk:4

D:\tmp\1.0.x>svn pg svn:mergeinfo .
/trunk:4

D:\tmp\1.0.x>svn mergeinfo file:///D:/tmp/repos/trunk
r4 ← マージ済みのリビジョン

D:\tmp\1.0.x>svn mergeinfo --show-revs merged   file:///D:/tmp/repos/trunk
r4 ← マージ済みのリビジョン

D:\tmp\1.0.x>svn mergeinfo --show-revs eligible file:///D:/tmp/repos/trunk
r5 ← 未マージのリビジョン

再度、リビジョン4 を trunk → ブランチ 1.0.x にマージしてみる

D:\tmp\1.0.x>svn merge -c 4 file:///D:/tmp/repos/trunk
                                                     ← 何も行われない。
D:\tmp\1.0.x>svn di

D:\tmp\1.0.x>