|
Continuing CVS: Tags, Branches, triggers and CVSWEB.
Table of Contents
1. CVS
1.1 CVS?
1.2 Where can I get started with CVS?
2. Tagging
2.1 Tagging?
2.2 cvs tag
2.3 cvs rtag
2.4 Retrieving a tag later.
3. Branching
3.1 Branching?
3.2 cvs tag -b
3.3 cvs rtag -b
3.4 Obtaining a working copy of the branch
4. Merging
4.1 Merging?
4.2 What CVS doesn't do.
4.3 What you do.
5. Triggers
5.1 Triggers?
5.2 commitinfo checks
5.3 loginfo scripts.
5. CVSWEB
5.1 CVSWEB?
1. CVS
1.1 CVS?
CVS stands for Concurrent Version System. It is a system
which allows multiple developers to maintain a codebase,
in a manner similar to many other source control systems
out there, such as Microsoft Visual Sourcesafe, arch,
subversion and BitKeeper.
1.2 Where can I get started with CVS?
I can recommend nothing better than
my own tutorial on the subject
. I've
recieved a lot of feedback on it, and it's a good guide for
the practical setup. O' Reilly have a booklet on it, although
I can't vouch for the quality of it. If CVS still confuses
you, read the first tutorial. This tutorial is not for
beginners.
Let's get right to it.
2. Tagging
2.1 Tagging
So, you've got your CVS server all set up, and your code
has been running along nicely in it for some time now. You
have a major release coming up. You'd like to somehow
snapshot the source at a given point in time, and say "That
was Version v0.1". Perhaps to retrieve it later, or just
for completeness. This is where tagging comes in. Tagging
is basically placing a 'tag' on each file, no matter what
revision number it's at. This can be done either to a working
copy, or to the repository itself. The effects are the same.
2.2 cvs tag
If you have a working copy, then use the 'cvs tag' command
to tag it. In our example 'MyProject' module, I've done
some nice stuff to my source, and decide to do a dot-release.
Say I want to go to Version 0.2beta1. The tag must start
with an alphabetic character, and cannot use certain
characters, such as fulltops, so I decide to use 'v0_2beta1'
as the tag name. Observe.
~/ doc@flaherty $ cd cvswork/MyProject/
~/cvswork/MyProject/ doc@flaherty $ cvs tag v0_2beta1
cvs tag: Tagging .
cvs tag: Tagging doc
T doc/INSTALL
T doc/README
cvs tag: Tagging src
T src/main.c
T src/main.h
T src/something.c
T src/something.h
~/cvswork/MyProject/ doc@flaherty $
I cd into the base of the working directory, and issue the
tag command. This tags the MyProject module with the
v0_2beta1 identifier.
2.3 cvs rtag
If you don't have, or don't want to check out a working
copy, you may use the 'cvs rtag' command, without having a
checked-out revision. Simple. Like before, I decide to tag
my current revision as being 'v0_2beta1'.
~/ doc@flaherty $ cvs rtag v0_2beta1 MyProject
cvs rtag: Tagging MyProject
cvs rtag: Tagging MyProject/doc
cvs rtag: Tagging MyProject/src
The project is now tagged, in the exact same way as it would
have been if I had used 'cvs tag' as above.
That's as simple and as difficult as tagging gets.
2.4 Retrieving a tag later.
Feeling nostalgic? Fast forward a few years, and you feel
like inspecting the code for v0_2beta1. Easy!
~/scratch/ doc@flaherty $ cvs checkout -rv0_2beta1 MyProject
cvs checkout: Updating MyProject
cvs checkout: Updating MyProject/doc
U MyProject/doc/INSTALL
U MyProject/doc/README
cvs checkout: Updating MyProject/src
U MyProject/src/main.c
U MyProject/src/main.h
U MyProject/src/something.c
U MyProject/src/something.h
You now have your code, as it was when it was tagged as
v0_2beta1.
3. Branching
3.1 Branching
Branching, also known as forking, is when a codebase 'splits'
into two codebases temporarily. For example, in a system
with a cyclic release cycle, there could be a branch for
development code (i.e. features that are new going in, added
support for widget/library X, and other things that you
don't want on your production system yet), and a bugfix/service
patch branch, which retains the same featureset, while
applying interim bugfixes that are more demanding then your
release cycle's span. The potential nightmare of merging
these two branches is then left to just before the release
deadline .
When a CVS module is created, it has one 'central branch',
colloquially and sensibly known as 'the trunk'. The tag
name for this branch is always 'HEAD'. Most branches are
branched off HEAD, to be merged later, or not, as the case
may be.
Let's go into how to branch a module.
3.2 cvs tag -b
Confusingly enough, CVS thinks of branches in terms of tags.
A tag can be either what I call a 'snapshot tag', or a
'branch tag'. A snapshot tag is just that, as described
above. A Branch Tag is an identifier that refers to a branch
of the code, that revisions can be checed into instead of
checked into HEAD.
My Imaginary Project is having a 0.3 release in four months.
However, there are bugfix requests coming in, as they do
with all projects. I want to seperate the effort of servicing
these requests, and that of adding features for 0.3. So, I
decide to create a branch, called 'v0_3_bugfix'.
~/ doc@flaherty $ cd cvswork/MyProject/
~/cvswork/MyProject/ doc@flaherty $ cvs tag -b v0_2_bugfix
cvs tag: Tagging .
cvs tag: Tagging doc
T doc/INSTALL
T doc/README
cvs tag: Tagging src
T src/main.c
T src/main.h
T src/something.c
T src/something.h
The code is now branched.
3.3 cvs rtag -b
Similarly to cvs tag, cvs rtag may also be used in the same
way to branch a module (See Section 2.3). Be sure to include
the -b option.
3.4 Obtaining a working copy of the branch
This is also done in the same way that you would check out
a tag (See section 2.4). The difference is that if you
commit work done in theis working copy, it is committed to
the branch, and not the trunk. So, bugfix developers would
work on this branch, whereas new feature developers work
on HEAD.
This concludes the explanation of branching.
4. Merging
4.1 Merging?
When two branches need to be 'merged' (i.e. in our example,
to consolidate the new features in HEAD with the bugfixes
from v0_2_bugfix), we merge them. This brings us back to
having one branch (in this case, just the trunk).
4.2 What CVS doesn't do
CVS doesn't merge branches for you in the sense you might
be thinking. There will be differences between the files
in different branches that would be impossible to merge
programattically. Instead, CVS tries its best, and after
that, it's up to you.
4.3 What you do.
Here's how to merge two branches. There will almost definitely
be conflicts, so I'll walk you through a simple one.
First, we check out HEAD.
~/mrgdir/ doc@flaherty $ cvs co MyProject
cvs checkout: Updating MyProject
cvs checkout: Updating MyProject/doc
U MyProject/doc/INSTALL
U MyProject/doc/README
cvs checkout: Updating MyProject/src
U MyProject/src/main.c
U MyProject/src/main.h
U MyProject/src/something.c
U MyProject/src/something.h
Now, we want to try to merge the two branches. This can be
done for individual files, but we'll do it for the entire
module here, since I know only one file will cause issues.
~/mrgdir/MyProject/ doc@flaherty $ cvs update -j v0_2_bugfix
cvs update: Updating .
cvs update: Updating doc
cvs update: Updating src
RCS file: /usr/local/cvsroot/MyProject/src/main.c,v
retrieving revision 1.1
retrieving revision 1.1.2.1
Merging differences between 1.1 and 1.1.2.1 into main.c
rcsmerge: warning: conflicts during merge
CVS is telling us that we need to merge some differences
manually. So, we look at the src directory:
~/mrgdir/MyProject/src/ doc@flaherty $ ls -al
total 10
drwx------ 3 doc 1002 512 Aug 27 21:50 .
-rw------- 1 doc 1002 83 Aug 27 21:40 .#main.c.1.2
drwx------ 5 doc 1002 512 Aug 27 21:50 ..
drwx------ 2 doc 1002 512 Aug 27 21:50 CVS
-rw-r--r-- 1 doc 1002 212 Aug 27 21:50 main.c
-rw-r--r-- 1 doc 1002 0 Aug 27 21:04 main.h
-rw-r--r-- 1 doc 1002 0 Aug 27 21:04 something.c
-rw-r--r-- 1 doc 1002 0 Aug 27 21:04 something.h
CVS saves our copy of main.c as '.#main.c.1.2' (1.2 is the
revision number of main.c in HEAD). main.c looks like this:
<<<<<<< main.c
#include <stdio.h>
int main(void)
{
printf("This is MyProject Version 0.3n");
}
=======
#include <stdio.h>
int main(void)
{
printf("This is MyProject Version 0.2-bugfixn");
}
>>>>>>> 1.1.2.1
So, it looks pretty basic (although manual merges can get
quite complex!). Merge the changes in the file. When you're
done, commit the merged code from this working directory.
It will be committed into HEAD.
Once all merges are taken care of, you've merged v0_2_bugfix
into HEAD. The branch tag is still there, but it can be
ignored, once nobody is committing to it.
5. Triggers
5.1 Triggers?
Triggers are used by CVS to perform certain checks on files
being checked into CVS, to do certain things with log
messages, and such and such. The most commonly-used ones
are commitinfo checks, and loginfo scripts.
5.2 commitinfo checks
The file 'commitinfo' in the CVSROOT administration module
defines checks to be executed when any files are committed.
These checks run on the server side. If the program defined
returns a non-zero return code, the commit will be aborted.
This can be useful for doing quick tests on code (i.e.
running it through the C preprocessor, running indent on
it, etc).
The format of lines in this file is as follows:
/file regex/ /path/to/program
If the name of the file being committed matches the regex
(relative to the CVSROOT directory on the server), then the
program is run. The full path to the directory the file is
in on the server, and the filename itself are appended to
any arguments you supply to the script. For example, I add
this to my $CVSROOT/commitino file:
^MyProject /root/scripts/blah.pl
Now, whenever I commit a file in MyProject, /root/scripts/blah.pl
is run, with arguments being the directory the files I'm
commiting are in on the server, and then a list of files
being committed. The contents of blah.pl are left as an
exercise to the reader.
5.3 loginfo scripts.
Loginfo scripts work in a similar basis to commitinfo checks,
except they are run after successful commit. A good example
is:
^MyProject cat | mail someguys@mycompany.com
In loginfo entries, the log entered for the commit is the
stdin of the program run. The following identifiers are
also expanded:
%s : The filename committed.
%V : The old version number of the file.
%v : The new version number of the file.
The above example will send an email on each successful commit.
6. CVSWEB
6.1 CVSWEB?
CVSWEB is a
read-only web interface to cvs, allowing you to view a
revision of a file, view diffs of different revisions, and
browse available modules. It's an invaluable tool for giving
people access to the code, for code familiarisation. It's
also good for giving a link to a specific revision of a
file, for example, in a bugnote in your bug-tracking system. Related: Getting Started with CVS Managing Access with CVS Subversion - a better CVS
About the author, Dave O Connor.
USERS COMMENTS
First I thought that how can I get the proper document regarding CVS, so that I can start work on this. Then I came to know about this site. Really it is very good & very helpfull.
Thanks a lot.
|