ServicesSoftwareAbout Us |
Go to the first, previous, next, last section, table of contents.
3 Advanced UsageNow that you've become familiar with the basic usage of CVS, it's time to move to more advanced uses. 3.1 Using branchesOne common theme that comes up is that of branching support in CVS. Branching is used to manage the parallel development process in a logical fashion. However, it's important to point out that CVS merely provides a convenient mechanism for branching; it does not mandate policy decisions that detail how branching is used to manage parallel development. Policy decisions are beyond the scope of a tutorial; it's better to see some of the possibilities to understand how branching can help with common development scenarios. (It's up to you and your team to develop policies that fit your team's working style.) For now, it's time to explore some of these scenarios. 3.1.1 Tracking changes to a released versionOne very common use of branching is accommodating modifications to a released version. Branching in this case allows the changes to be stored on a separate line of development, isolated from any experimental code in the current version of the program. CVS allows these changes to be merged later to a future version.
Coming back to the `hello' sample, assume for the moment that
you've been asked by a customer, WidgetCo, to add support for supplying
the greeting via an environment variable. The customer is using the
A branch can be created in CVS using the rtag command. The tag name establishes the branch name used by CVS. Now that you've been requested to implement this new feature, you can start by creating a new branch to store your changes: $ cvs rtag -b -r hello-1_0_1 hello-1_0_1-branch hello cvs rtag: Tagging hello cvs rtag: Tagging hello/doc cvs rtag: Tagging hello/src
It's a good idea to have the branch tag include the Now that the branch has been created in the CVS repository, you can check out the code to begin making the required changes (the co is an alias for checkout): $ cd $T/w $ cvs co -r hello-1_0_1-branch -d hello-br hello cvs checkout: Updating hello-br U hello-br/Changelog U hello-br/Makefile cvs checkout: Updating hello-br/doc U hello-br/doc/README cvs checkout: Updating hello-br/src U hello-br/src/hello.c $ cd hello-br The `-r' option for checkout can be used to specify a particular revision. In this case, a branch name was given instead of tag or revision number. If a branch name is used with `-r', CVS uses the most recent file revisions on the specified branch. The `-d' option tells CVS to check out the code into the specified directory; the directory is created if it doesn't exist. You can view which branch your working directory is using by using the CVS status command: $ cvs status cvs status: Examining . =================================================================== File: Changelog Status: Up-to-date Working revision: 1.1.1.1 Mon Aug 5 17:29:19 2002 Repository revision: 1.1.1.1 /home/alcocer/sb/r/hello/Changelog,v Sticky Tag: hello-1_0_1-branch (branch: 1.1.1.1.2) Sticky Date: (none) Sticky Options: (none) =================================================================== File: Makefile Status: Up-to-date Working revision: 1.1.1.1 Mon Aug 5 17:29:19 2002 Repository revision: 1.1.1.1 /home/alcocer/sb/r/hello/Makefile,v Sticky Tag: hello-1_0_1-branch (branch: 1.1.1.1.2) Sticky Date: (none) Sticky Options: (none) cvs status: Examining doc =================================================================== File: README Status: Up-to-date Working revision: 1.1.1.1 Mon Aug 5 17:29:19 2002 Repository revision: 1.1.1.1 /home/alcocer/sb/r/hello/doc/README,v Sticky Tag: hello-1_0_1-branch (branch: 1.1.1.1.2) Sticky Date: (none) Sticky Options: (none) cvs status: Examining src =================================================================== File: hello.c Status: Up-to-date Working revision: 1.2 Mon Aug 5 17:29:19 2002 Repository revision: 1.2 /home/alcocer/sb/r/hello/src/hello.c,v Sticky Tag: hello-1_0_1-branch (branch: 1.2.2) Sticky Date: (none) Sticky Options: (none)
Looking at the output, you'll notice that there is a "sticky" tag; CVS
will save the branch name that corresponds to the revision specified via
`-m'. CVS does this by storing the branch name in each
`CVS' directory present in your working sub-directories. Any
future updates or commits that are run while inside of the work
directory `$T/w/hello-br' will be relative to the
`$T/d/hello-1.0- getenv.patch' to review the changes. Once you've completed the changes, use the CVS diff command to review them:
$ cvs diff -ub
cvs diff: Diffing .
cvs diff: Diffing doc
cvs diff: Diffing src
Index: src/hello.c
===================================================================
RCS file: /home/alcocer/sb/r/hello/src/hello.c,v
retrieving revision 1.2
diff -u -b -r1.2 hello.c
--- src/hello.c 2002/08/05 19:16:07 1.2
+++ src/hello.c 2002/08/06 23:31:50
@@ -1,7 +1,14 @@
#include <stdio.h>
+#include <stdlib.h>
int main(int argc, char *argv[])
{
- printf("Hello, world.\n");
+ char *msg;
+
+ msg = getenv("HELLOMSG");
+ if (msg == NULL)
+ msg = "Hello, world.";
+
+ printf("%s\n", msg);
return 0;
}
Notice that the differences shown do not include any of the new code added for version 1.0.2; CVS knows that the working directory `$T/w/hello-br' is not using the main trunk. Now that the requested feature has been implemented, it's time to check it in: $ cvs ci -m "Added HELLOMSG environment variable requested by WidgetCo." cvs commit: Examining . cvs commit: Examining doc cvs commit: Examining src Checking in src/hello.c; /home/alcocer/sb/r/hello/src/hello.c,v <-- hello.c new revision: 1.2.2.1; previous revision: 1.2 done
If you examine the output of the commit, you'll see the branching that
took place for `src/hello.c'. The previous revision was
$ cvs status -v src/hello.c =================================================================== File: hello.c Status: Up-to-date Working revision: 1.2.2.1 Tue Aug 6 23:31:50 2002 Repository revision: 1.2.2.1 /home/alcocer/sb/r/hello/src/hello.c,v Sticky Tag: hello-1_0_1-branch (branch: 1.2.2) Sticky Date: (none) Sticky Options: (none) Existing Tags: hello-1_0_1-branch (branch: 1.2.2) hello-1_0_2 (revision: 1.4) hello-1_0_1 (revision: 1.2) hello-1_0 (revision: 1.1.1.1) acme (branch: 1.1.1)
Remembering that the Once you've completed the changes for your hypothetical customer, you can celebrate now by tagging the release: $ cvs tag hello-1_0_1-p1 cvs tag: Tagging . T Changelog T Makefile cvs tag: Tagging doc T doc/README cvs tag: Tagging src T src/hello.c Now that you're done with the `hello-br' working directory, you can get rid of it using the CVS release command. The command will prompt you to confirm you want to proceed: $ cd .. $ cvs release -d hello-br ? hello You have [0] altered files in this repository. Are you sure you want to release (and delete) directory `hello-br': y Examining the output before the prompt, you'll see that `hello' is listed with a question mark; CVS is telling you that the `hello' program is not checked into CVS. It does this to warn you that if you decide to delete this working directory, you may be losing a file that should be checked into CVS. Since binary programs aren't usually checked into CVS, this warning is fine. Later, you'll see how to tell CVS to ignore object files and program files. For now, you can answer yes and delete the repository. This branching example shows how you can track source code changes required by customers, while keeping your current source code isolated from these changes. CVS also helps you manage changes made to your software suppliers, again isolating your current sources from potentially disruptive changes, until you're ready to merge the new code into your main trunk. 3.1.2 Integrating third-party releasesAnother common branching scenario is updating locally modified, vendor-supplied software so that your local modifications are retained. CVS allows you to control how and when vendor-supplied releases are merged into your main trunk, using the sophisticated automatic merging you've already seen.
Assume that you've been notified by Acme that release $ cd $T/w $ tar xzvf $T/d/hello-1.1.tar.gz hello-1.1/ hello-1.1/src/ hello-1.1/src/hello.c hello-1.1/doc/ hello-1.1/doc/README hello-1.1/Makefile hello-1.1/Changelog $ cd hello-1.1 $ cvs import -m "hello-1.1 released by Acme Corp." hello acme hello-1_1 U hello/Makefile U hello/Changelog cvs import: Importing /home/alcocer/sb/r/hello/src C hello/src/hello.c cvs import: Importing /home/alcocer/sb/r/hello/doc U hello/doc/README 1 conflicts created by this import. Use the following command to help the merge: cvs checkout -jacme:yesterday -jacme hello
The conflict message CVS displays is letting you know that when you
perform the merge, you will have a change conflict to resolve in
`src/hello.c'. This is because the new As before, once the import takes place, you have no need to keep the source code used to perform the import, and you can safely delete it: $ cd .. $ rm -fr hello-1.1
At this point, the source code for version Now that you have some time, you'd like to merge the new release into your main trunk. Now, go ahead and perform the merge in a separate directory, `hello-merge', so that you don't have to deal with your current changes at the same time you're trying to perform the merge. First, check out the current version of `hello' stored in the CVS repository: $ cvs co -d hello-merge hello cvs checkout: Updating hello-merge U hello-merge/Changelog U hello-merge/Makefile cvs checkout: Updating hello-merge/doc U hello-merge/doc/README cvs checkout: Updating hello-merge/src U hello-merge/src/hello.c $ cd hello-merge
Next, tell CVS to merge the changes between version $ cvs update -jhello-1_0 -jhello-1_1 cvs update: Updating . cvs update: Updating doc cvs update: Updating src RCS file: /home/alcocer/sb/r/hello/src/hello.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 hello.c rcsmerge: warning: conflicts during merge Notice the conflict warning; this is the conflict import was warning you about before. You can use update to see which files have conflicts: $ cvs update cvs update: Updating . cvs update: Updating doc cvs update: Updating src C src/hello.c The new version of `hello' includes support for a `-l' option to specify the language the greeting is in. You'll want to merge this feature by having `-l' override any greeting or name specified on the command line. After you make the changes, review them:
$ cvs diff -ub
cvs diff: Diffing .
cvs diff: Diffing doc
cvs diff: Diffing src
Index: src/hello.c
===================================================================
RCS file: /home/alcocer/sb/r/hello/src/hello.c,v
retrieving revision 1.4
diff -u -b -r1.4 hello.c
--- src/hello.c 2002/08/08 15:04:37 1.4
+++ src/hello.c 2002/08/08 18:11:11
@@ -1,10 +1,49 @@
#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+struct langmap
+{
+ char *code;
+ char *msg;
+};
+
+struct langmap langtbl[] =
+{
+ { "en", "Hello, world" },
+ { "es", "Hola, mundo" },
+ { "it", "Saluti, mondo" },
+ { "fr", "Bonjour, monde" },
+ { "de", "Hallo, Welt" }
+};
+
+#define LANGTBL_SIZE (sizeof(langtbl) / sizeof(langtbl[0]))
+
int main(int argc, char *argv[])
{
+ int i, msgi = 0;
char *name = "world";
char *greeting = "Hello";
+ if (getopt(argc, argv, "l:") != -1)
+ {
+ for (i = 0; i < LANGTBL_SIZE; i++)
+ {
+ if (strcmp(optarg, langtbl[i].code) == 0)
+ {
+ msgi = i;
+ break;
+ }
+ }
+ if (i == LANGTBL_SIZE)
+ {
+ fprintf(stderr, "hello: error: unsupported language code '%s', "
+ "using default language\n", optarg);
+ }
+ printf("%s.\n", langtbl[msgi].msg);
+ }
+ else
+ {
if (argc > 1)
greeting = argv[1];
@ -12,6 +51,7 @
name = argv[2];
printf("%s, %s.\n", greeting, name);
+ }
return 0;
}
+ {
if (argc > 1)
greeting = argv[1];
@ -12,6 +51,7 @
name = argv[2];
printf("%s, %s.\n", greeting, name);
+ }
return 0;
}
Now that the merge is complete and working, check your changes in and tag your new release: $ cvs ci -m "Merged hello-1.1 release." cvs commit: Examining . cvs commit: Examining doc cvs commit: Examining src Checking in src/hello.c; /home/alcocer/sb/r/hello/src/hello.c,v <-- hello.c new revision: 1.5; previous revision: 1.4 done $ cvs tag hello-1_1_1 cvs tag: Tagging . T Changelog T Makefile cvs tag: Tagging doc T doc/README cvs tag: Tagging src T src/hello.c 3.2 ConclusionHopefully this short tutorial has introduced you to enough of CVS that you're able to use it productively on a daily basis. Of course, there is more to CVS than a short tutorial can cover, and you are encouraged to review the manual to become more familiar with it. Go to the first, previous, next, last section, table of contents. |