ノード:Multiple Merges, 次:, 前:Merging Changes From Branch To Trunk, 上:Branches



Multiple Merges

トランクにマージした後にも、ブランチ上での開発が続くことがあります。たと えば前のリリース版に2つめのバグが見つかった場合、それはブランチ上でバグ フィクスされますね。random.c の冗談がわからない人がいたとしましょう、そ うするとブランチ上でそれを説明する行をつけ加えなければいけません、

floss$ pwd
/home/whatever/myproj_branch
floss$ cat b-subdir/random.c
/* Print out a random number. */
#include <stdio.h>
void main ()
{
  printf ("A random number.\n");
  printf ("Get the joke?\n");
}
floss$

そしてコミットします。このバグフィクスもトランクにマージする必要がある場 合、トランクの作業コピーに再マージするため、前回と同じように update コマ ンドを走らせようとしてしまうと思います:

floss$ cvs -q update -j Release-1999_05_01-bugfixes
RCS file: /usr/local/cvs/myproj/hello.c,v
retrieving revision 1.5
retrieving revision 1.5.2.1
Merging differences between 1.5 and 1.5.2.1 into hello.c
RCS file: /usr/local/cvs/myproj/b-subdir/random.c,v
retrieving revision 1.2
retrieving revision 1.2.2.2
Merging differences between 1.2 and 1.2.2.2 into random.c
rcsmerge: warning: conflicts during merge
floss$

ごらんの通り、望んだ結果は得られません。あれからトランクには変更を加えて いないからコンフリクトは起こらないはず、のような気がするのに、起こってし まいました。

この問題は update コマンドが説明した通りの動作をしたことによって起こりま した: ブランチの根と先端の変更を計算して、現在の作業コピーにマージする、 のです。問題はこれらの変更のうちのいくつかが既に作業コピーにマージされて いた、ということにありました。だからコンフリクトしたのです:

floss$ pwd
/home/whatever/myproj
floss$ cat b-subdir/random.c
/* Print out a random number. */
#include <stdio.h
void main ()
{
<<<<<<< random.c
  printf ("A random number.\n");
=======
  printf ("A random number.\n");
  printf ("Get the joke?\n");
>>>>>>> 1.2.2.2
}
floss$

これらのコンフリクトを手で解消してもかまいません、各ファイルそれぞれやっ てね、と言うのは簡単なことです。まあでも最初っからコンフリクトしないよう にするほうがいいですよね。-j フラグを1つではなく2つ渡すことによって、ブ ランチの根からでなく以前のマージのところから先端までの変更をマージするこ とができます。最初の -j はブランチ上の開始地点、2つめはただブランチ名だ けを書けばいいです(これはブランチの先端という意味になります)。

問題は、どうやってブランチ上で以前のマージの点を指定すればいいか、という ことです。ブランチタグ名に日付をつけて指定するのが1つの方法です。CVS は このために特別な書きかたを用意しています:

floss$ cvs -q update -j "Release-1999_05_01-bugfixes:2 days ago" \
                     -j Release-1999_05_01-bugfixes
RCS file: /usr/local/cvs/myproj/b-subdir/random.c,v
retrieving revision 1.2.2.1
retrieving revision 1.2.2.2
Merging differences between 1.2.2.1 and 1.2.2.2 into random.c
floss$

ブランチタグ名にコロンと日付をつなげると(普通の CVS の日付指定のやりかた ならどれでもいいです)、CVS はその日付以降の変更を取ってきます。最初のバ グフィクスが3日前にコミットされたのを知っていれば、上記のコマンドで2つめ のバグフィクスだけをマージできます。

もう少し良い方法は、前もってやっとかないとだめなんですが、各バグフィクス の後にブランチにタグをつけておく方法です(普通のタグです、新しいブランチ を分岐させたりするようなやつではなくて)。バグをフィクスしてコミットした ら、ブランチの作業コピーでこういうのを実行してください:

floss$ cvs -q tag Release-1999_05_01-bugfixes-fix-number-1
T README.txt
T hello.c
T a-subdir/whatever.c
T a-subdir/subsubdir/fish.c
T b-subdir/random.c
floss$

こうしておけば、2つめの変更をトランクにマージする時にはこのタグを使って、 簡単に前のリビジョンと区別をつけられます。

floss$ cvs -q update -j Release-1999_05_01-bugfixes-fix-number-1 \
                     -j Release-1999_05_01-bugfixes
RCS file: /usr/local/cvs/myproj/b-subdir/random.c,v
retrieving revision 1.2.2.1
retrieving revision 1.2.2.2
Merging differences between 1.2.2.1 and 1.2.2.2 into random.c
floss$

変更を加えたのが何日前だったか、とか思い出さないといけない方法より、この 方法のほうが断然いいのですが、この方法を使おうとするとトランクにマージす るたびにブランチにタグをつけるのを忘れないようにせねばなりません。この話 の教訓は、前もって、度々タグをつけよ、ということですね。タグは少なすぎる より多すぎるほうがマシです(説明的な名前をつけている限りにおいてはです)。 たとえば上の例で言うと、ブランチ上の新しいタグ名はブランチタグと似ている 必要はないわけです。ですから簡単に fix1 という名前をつけてもよかっ たのですが、Release-1999_05_01-bugfixes-fix-number-1 という名前に しました。他のブランチのタグと混同しないためには後者のほうがいいのです。 (タグ名はブランチ内でユニークではなく、ファイル内でユニークであることを 思い出してください。別のブランチだからといって、同じファイルに fix1 という名前のタグをふたつつけたりはできません。)