ノード:Tracking Third-Party Sources (Vendor Branches), 次:, 前:Going Out On A Limb (How To Work With Branches And Survive), 上:Advanced CVS



Tracking Third-Party Sources (Vendor Branches)

外部の配布元から取ってきたソフトウェアに、あるサイトでローカルな変更 が加えられることがあります。そのローカルな変更を配布元が受け入れない 場合(そうできないについて正当な理由はいくらでも考えられます)、そのサ イトはそのソフトウェアのアップグレードを受け取るたびにその変更をメン テせねばなりません。

CVS の ベンダブランチ(vendor branches) という機能がこの仕事に 役立ちます。ベンダブランチというのは cvs import のわけのわからない最 後の2つの引数の説明でした(今まではね)。An Overview of CVS でこ じつけたベンダタグとリリースタグのことです。

ここで、それがどのように動くか示します。最初のインポートは他の CVS プロジェクトの最初のインポートと同様です(ちょっと注意してベンダタグ とリリースタグを決めないといけませんが):

floss$ pwd
/home/jrandom/theirproj-1.0
floss$ cvs import -m "Import of TheirProj 1.0" theirproj Them THEIRPROJ_1_0
N theirproj/INSTALL
N theirproj/README
N theirproj/src/main.c
N theirproj/src/parse.c
N theirproj/src/digest.c
N theirproj/doc/random.c
N theirproj/doc/manual.txt

No conflicts created by this import

floss$

そしてどこかに作業コピーをチェックアウトして、ローカルな変更を施し、 その後コミットして下さい:

floss$ cvs -q co theirproj
U theirproj/INSTALL
U theirproj/README
U theirproj/doc/manual.txt
U theirproj/doc/random.c
U theirproj/src/digest.c
U theirproj/src/main.c
U theirproj/src/parse.c
floss$ cd theirproj
floss$ emacs src/main.c src/digest.c
 ...
floss$ cvs -q update
M src/digest.c
M src/main.c
floss$ cvs -q ci -m "changed digestion algorithm; added comment to main"
Checking in src/digest.c;
/usr/local/newrepos/theirproj/src/digest.c,v  <--  digest.c
new revision: 1.2; previous revision: 1.1
done
Checking in src/main.c;
/usr/local/newrepos/theirproj/src/main.c,v  <--  main.c
new revision: 1.2; previous revision: 1.1
done
floss$

1年後、そのソフトウェアの次のバージョンが Them, Inc. から届きます。 ローカルの変更をそのバージョンにも取り入れなければなりません。配布元 での変更とローカルの変更は、少しだけ重なっているところがあります。配 布元では新しいファイルを一つ追加し、あなたの触ってないファイル2つを 変更し、あなたが触ったファイル2つにも変更を加えています。

まずやることは、もう1度インポートすることです。今回は新しいソースか らインポートします。初回インポートとほとんど同じです。リポジトリ中、 以前と同じプロジェクトの、同じベンダブランチにインポートします。違う のはリリースタグだけです:

floss$ pwd
/home/jrandom/theirproj-2.0
floss$ cvs -q import -m "Import of TheirProj 2.0" theirproj Them THEIRPROJ_2_0
U theirproj/INSTALL
N theirproj/TODO
U theirproj/README
cvs import: Importing /usr/local/newrepos/theirproj/src
C theirproj/src/main.c
U theirproj/src/parse.c
C theirproj/src/digest.c
cvs import: Importing /usr/local/newrepos/theirproj/doc
U theirproj/doc/random.c
U theirproj/doc/manual.txt

2 conflicts created by this import.
Use the following command to help the merge:

       cvs checkout -jThem:yesterday -jThem theirproj

floss$

おやまあ、CVS がこんな風に助けようとしてくれたのは今まで見たことがあ りませんね。変更をマージするためにどんなコマンドを実行するか教えてく れています。それに、ほとんど正しいですよ! 実際、示されたコマンドは動 きますが(yesterday のところを、最初のインポートを含んでいるが2番目の インポートを含んでいない時間間隔に調整したとして)、著者は代わりにリ リースタグを使うほうが好きです:

floss$ cvs checkout -j THEIRPROJ_1_0 -j THEIRPROJ_2_0 theirproj
cvs checkout: Updating theirproj
U theirproj/INSTALL
U theirproj/README
U theirproj/TODO
cvs checkout: Updating theirproj/doc
U theirproj/doc/manual.txt
U theirproj/doc/random.c
cvs checkout: Updating theirproj/src
U theirproj/src/digest.c
RCS file: /usr/local/newrepos/theirproj/src/digest.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
Merging differences between 1.1.1.1 and 1.1.1.2 into digest.c
rcsmerge: warning: conflicts during merge
U theirproj/src/main.c
RCS file: /usr/local/newrepos/theirproj/src/main.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
Merging differences between 1.1.1.1 and 1.1.1.2 into main.c
U theirproj/src/parse.c
floss$

インポートでコンフリクトが2つあるというふうに表示されたのに、マージ ではコンフリクトが1つしかないことに注意して下さい。インポートとその 他ではコンフリクトが少し違うものだと CVS が思っているように見えます。 インポートでは基本的に、前回のインポートと今回のインポートの間に、あ なたとベンダ両方が変更したファイルをコンフリクトとして報告します。し かしマージの時点になると、「コンフリクト」の通常の定義に忠実なのです。 つまり、変更が重なっている、という意味になります。重なり合っていない 変更は通常の方法でマージされ、そのファイルはただの変更として示されま す。

ちょっと diff を取ってみると、ファイルのうち1つだけにコンフリクトマー カがあることがわかります:

floss$ cvs -q update
C src/digest.c
M src/main.c
floss$ cvs diff -c
Index: src/digest.c
===================================================================
RCS file: /usr/local/newrepos/theirproj/src/digest.c,v
retrieving revision 1.2
diff -c -r1.2 digest.c
*** src/digest.c        1999/07/26 08:02:18     1.2
-- src/digest.c        1999/07/26 08:16:15
***************
*** 3,7 ****
-- 3,11 ----
 void
 digest ()
 {
+ <<<<<<< digest.c
   printf ("gurgle, slorp\n");
+ =======
+   printf ("mild gurgle\n");
+ >>>>>>> 1.1.1.2
 }
Index: src/main.c
===================================================================
RCS file: /usr/local/newrepos/theirproj/src/main.c,v
retrieving revision 1.2
diff -c -r1.2 main.c
*** src/main.c  1999/07/26 08:02:18     1.2
-- src/main.c  1999/07/26 08:16:15
***************
*** 7,9 ****
-- 7,11 ----
 {
   printf ("Goodbye, world!\n");
 }
+
+ /* I, the vendor, added this comment for no good reason. */
floss$

こうなると他のマージと同じように、ただコンフリクトを解消すればいいだ けの話になります:

floss$ emacs  src/digest.c  src/main.c
 ...
floss$ cvs -q update
M src/digest.c
M src/main.c
floss$ cvs diff src/digest.c
cvs diff src/digest.c
Index: src/digest.c
===================================================================
RCS file: /usr/local/newrepos/theirproj/src/digest.c,v
retrieving revision 1.2
diff -r1.2 digest.c
6c6
<   printf ("gurgle, slorp\n");
--
>   printf ("mild gurgle, slorp\n");
floss$

そして変更をコミットします

floss$ cvs -q ci -m "Resolved conflicts with import of 2.0"
Checking in src/digest.c;
/usr/local/newrepos/theirproj/src/digest.c,v  <--  digest.c
new revision: 1.3; previous revision: 1.2
done
Checking in src/main.c;
/usr/local/newrepos/theirproj/src/main.c,v  <--  main.c
new revision: 1.3; previous revision: 1.2
done
floss$

あとはベンダからの次のリリースを待つだけです。(もちろん、ローカルの 変更がちゃんと動くかどうかテストしたいだろうと思いますけれど!)

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