The original set of versions, before the branch was created, is called
the cvs co my_prog
. After a branch is created
the main line is still the default version. Unless you take special pains
to merge changes from a branch into the main line
or vice-versa, the changes that you make on a branch will never appear on
the main line, and vice-versa.
For example, when we cut a version of photo to bring to Fermilab for integration, we put it on a branch. If in the ensuing months some terrible bug were discovered in the cut version, without a branch we'd have two options: either cut a new version (based on whatever work we'd done since the last cut version) with all the attendent trouble and risk of bugs, or else ask the users of photo to struggle on working around the bug. With a branch we have another choice: we can fix the bug on the branch and cut a new version based on the branch. Because the only change made to photo since the last version is the bug fix, the normal worries and fresh bugs associated with a newly cut version are minimised.
The simplest way to create a branch called branchname
is to
cd to a copy of the code that you want to branch, say my_prog
,
and say:
which first names the branch's point of attachment (
cvs tag branchname_0
cvs tag -r branchname_0 -b branchname
branchname_0
),
and then actually creates the branch.
It's probably a good idea to update
first to check that your version really is up-to-date; I usually say
cvs -nq update
.
You are now ready to check out a copy of your branch.
If you want the original version of my_prog
to reside on
the new branch (i.e. the version that you ran the
taq
command on), now say
cvs update -r branchname
If you'd rather keep a copy of the main line as well as the new
branch, go to some directory that doesn't have the main line
checked out in it, and say
cvs co -r branchname my_prog
After either one of these last two paragraphs, any further work that
you do on the branched copy of my_prog
will automatically be
committed onto the branch. You can get very confused if you forget that
your files have been `poisoned' by the branch tag --- see the section
on sticky tags for details.
Let's ask cvs what it knows about some file on this branch; both
the branch name and the attachment point name are visible:
Note that the name
> cvs log my_prog/rhl.c
...
symbolic names:
branchname_0: 1.15
branchname: 1.15.0.2
v1_2: 1.9
V1_0: 1.1
branchname_0
refers to revision
1.15
, that is before the branch was made (branches on the revision
have names like 1.15.2.1
; see the section on
branch numbers for a discussion).
cvs ci file
will commit it to the branch. If you
have changed a file that isn't on the branch, you can commit it to the
branch with
cvs ci -r branchname file
The file will have a sticky tag set after this operation, that is cvs
will treat it as if it's on the branch, even though the rest of the
directory is still on the main line. (You can use cvs update -A
to get it back onto the main line but then your changes will seem to
disappear. See the section on merging for ways
to get your changes onto both the main line and the branch, as is often
desireable).
Due to a bug in cvs 1.3 (on which rcvs is currently based), if you add a new file in a directory checked out on a branch, the file will appear on the main line, not on your branch. Caveat scriptor.
cvs status
command. For example:
> cvs status my_prog/rhl.c
===================================================================
File: rhl.c. Status: Up-to-date
Version: 1.15.2.1 Mon Dec 12 12:05:04 1994
RCS Version: 1.15.2.1 /u/cvs/src/my_prog/rhl.c
Sticky Tag: branchname (revision: 1.15.2.1)
Sticky Date: (none)
Sticky Options: (none)
Tags themselves should be familiar --- they are simply what cvs calls the names that given to revisions, typically cut versions, and sticky tags are basically the corresponding names given to branches. They are called sticky because they stay attached to a file; once a file has a tag stuck to it, all future cvs commands applied to that file refer to the branch rather than to the main line of development.
For example, if you check in a revision onto the branch
branchname
with the command cvs ci -r branchname
rhl.c
and then someone adds some derogatory comments on the
main branch (i.e. they don't specify a tag with -r
), if
you issue the command cvs update rhl.c
you will
not see the changes. You'd have to say cvs
update -A rhl.c
to see them; the -A
flag tells cvs
to ignore sticky tags (and other sticky attributes --- see the cvs
manual for details). After using -A
your code is no longer
on the branch, and update
will no longer update your directory
with changes made to the branch.
co
or update
with the -j
flag, for example
to merge all changes made on branch branchname
into the
mainline, you'd find some directory which didn't have my_prog
checked out, and say:
cvs co -j branchname my_prog
(you could use update instead).
The very next thing to do is to tag the branch --- if you don't,
you'll never again be able to merge the branch into the main line without
gnashing of teeth. So do it:
(that reads, ``give the name
cvs rtag -r branchname branchname_1 my_prog
branchname_1
to the top of
branch branchname
'').
If ever you want to merge from the branch again, if you say:
you'll get lots of merge conflicts, because cvs will try to merge the
changes made before
cvs co -j branchname my_prog
branchname_1
for a second time. What you
want to say is:
As an alternative, you could cd to the main line, and say
cvs co -j branchname_1 -j branchname my_prog
After either of these commands you naturally immediately typed:
cvs update -j branchname_1 -j branchname
so as to be able to continue merging if more bugs appear in the future.
cvs rtag -r branchname branchname_2 my_prog
If you now said cvs log
, the output is discussed in
the section on branch numbers.
cvs log
you get a list of branch numbers as
maintained by RCS, the programme that cvs uses to actually manage files. They
are numbers such as 1.15
or 1.15.0.2
. It sometimes
helps to be able to interpret them when dealing with branches.
At the end of the section on merging, the output of
cvs log
would look something like:
Revisions on the main line have names such as
> cvs log my_prog/rhl.c
...
symbolic names:
branchname_2: 1.15.2.2
branchname_1: 1.15.2.1
branchname_0: 1.15
branchname: 1.15.0.2
v1_2: 1.9
V1_0: 1.1
1.9
, which means
the 9th revision since the file was created. RCS can handle numbers such
as 2.13
, but cvs never asks it to (although you could ask cvs
to ask RCS to do so, there'd be no point). Note that branchname_0
is on the main line; that's not unexpected as it was tagged before
any changes were committed to the branch.
The branch's tag branchname
has an RCS number of the form
1.15.0.2
; the .0.2
is cvs magic, but it means,
``a branch starting from 1.15''.
The numbers on the branch itself are 1.15.2.1
and
1.15.2.2
for the first and second changes made on the branch. Note
that they are not 1.15.0.3
as you might have expected;
more cvs magic.
If you branched the branch (which you could do if you were really
masochistic) you'd get version numbers such as 1.15.2.3.0.2
for the branch (twig?), and 1.15.2.3.2.1
for the first
change committed to the branch.