Copyright (C) 2000-2012 |
GNU Info (cvsbook.info)Tracking Third-Party Sources (Vendor Branches)Tracking Third-Party Sources (Vendor Branches) ============================================== Sometimes a site will make local changes to a piece of software received from an outside source. If the outside source does not incorporate the local changes (and there might be many legitimate reasons why it can't), the site has to maintain its changes in each received upgrade of the software. CVS can help with this task, via a feature known as "vendor branches". In fact, vendor branches are the explanation behind the puzzling (until now) final two arguments to cvs import: the vendor tag and release tag that I glossed over in Note: An Overview of CVS. Here's how it works. The initial import is just like any other initial import of a CVS project (except that you'll want to choose the vendor tag and release tag with a little care): 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$ Then you check out a working copy somewhere, make your local modifications, and commit: 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$ A year later, the next version of the software arrives from Them, Inc., and you must incorporate your local changes into it. Their changes and yours overlap slightly. They've added one new file, modified a couple of files that you didn't touch, but also modified two files that you modified. First you must do another import, this time from the new sources. Almost everything is the same as it was in the initial import - you're importing to the same project in the repository, and on the same vendor branch. The only thing different is the release tag: 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$ My goodness - we've never seen CVS try to be so helpful. It's actually telling us what command to run to merge the changes. And it's almost right, too! Actually, the command as given works (assuming that you adjust yesterday to be any time interval that definitely includes the first import but not the second), but I mildly prefer to do it by release tag instead: 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$ Notice how the import told us that there were two conflicts, but the merge only seems to claim one conflict. It seems that CVS's idea of a conflict is a little different when importing than at other times. Basically, import reports a conflict if both you and the vendor modified a file between the last import and this one. However, when it comes time to merge, update sticks with the usual definition of "conflict" - overlapping changes. Changes that don't overlap are merged in the usual way, and the file is simply marked as modified. A quick diff verifies that only one of the files actually has conflict markers: 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$ From here, it's just a matter of resolving the conflicts as with any other merge: 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$ Then commit the changes 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$ and wait for the next release from the vendor. (Of course, you'll also want to test that your local modifications still work!) ------------------------------------------------------------- |