cvs Basics

Improvements? Suggestions? email dna@hola.org

Minimal Info

update: (cvsup is equal to cvs -q up -dP)
cvsup
edit/modify the file:
g the_file.txt
see changes:
cvs di the_file.txt
if ok, then commit (make sure first all editors are closed!):
cvs ci the_file.txt
update-edit-view-diff-commit in one command using Hola's cvsed tool:
cvsed doc/procedure/support.txt

Basic Info

checkout

checkout whole ZON tree into sub-directory '.zon':
cvs co -d .zon zon:

checkout whole ZON tree into sub-directory 'zon2':
cvs co -d zon2 zon

faster, (but not garenteed clean) if you already have a checked out tree:
rm -rf .zon/build.*
cp -a .zon zon2
cd zon2
zcvs purge remove local modifications
cvsup

checkout just specific sub-tree to checkout zon/pkg/main into my_dir:
cvs co -d my_dir zon/pkg/main

update

check if we are updated with the server, without actually updating local file
cvs -n update

update local files from the server
cvs update (better: cvsup, faster-offline zcvs update)
possible results:
? unknown file - not in server, not in .cvsignore and not scheduled for add
M Modified
C (Conflict) Modified locally and on the server
U Updated on the server
P (Patched) Updated on the server (like U)
A scheduled for add
R scheduled for remove
better (does cvs -q up -dP): cvsup
fast offline: zcvs udate

update a specific file
cvs update my_app.c
better: cvsup my_app.c

diff

see differences between local file and server file
cvs diff my_app.c
better (g -d my_app.c): cvsdiff my_app.c

see differences between two versions on the server
cvs diff -r tag-0_1_10 -r tag-0_1_12 my_app.c

commit - Save your changes to the cvs repository

How to commit

first, update the file to make sure you are working on the latest copy the result of the update should be M on the file if the result is C then resolve the conflicts manually
cvs update my_app.c
make sure that only the lines you want to be commited will be commited
cvs diff my_app.c
commit the file, and write a short description of the change, for the other users to understand at a glance
cvs commit my_app.c
make sure that following the commit, the command line responds with success message

adding a new file
cvs add my_app.c
cvs commit my_app.c

or
cvs ci my_app.c

removing a file
rm my_app.c
cvs remove my_app.c

or
cvs rm my_app.c
cvs ci my_app.c


moving a file
There is no native move. A move is done by removing and adding the file again. The first line of the log message should be 'MOVED old --> new' and the file names should include the full path (include the repository name).
mv .zon/doc/design/db_design.txt .zon/doc/requirements/db.txt
cvs rm .zon/doc/design/db_design.txt
cvs add .zon/doc/requirements/db.txt
cvs ci .zon/doc/requirements/db.txt .zon/doc/design/db_design.txt

-----------------------------------------------------------
MOVED zon/doc/design/db_design.txt --> zon/doc/requirements/db.txt
moved documetation from design to requirements dir.
CVS:
CVS: Adding
CVS: new/new_name.txt
CVS: Removing:
CVS: old/old_name.txt
-----------------------------------------------------------

checking status of a file
gets local version of the file, and the server version
cvs stat my_app.c

see the list of commits to a file
cvs log my_app.c

see part of log relating to specific tag/branch:
cvs log -N -rTAG my_app.c

see who when and where a line was added/modified
# this will detect when the call to my_func() was added to the file
cvs annotate my_app.c | grep "my_func()"

adding a lot of new files and directroies:
DO NOT USE cvs import! IT IS BROKEN.
See 'importing 3rd party code' section below.

Code commit message

All code commits must have informative commit massage. The message should contain the 'why' while the diff is the what.

disable chrome
temporary disabling chrome testing while debugging sporadic BAT errors

Plan file commit message

Commit message for tasks file such as version_plan.txt can be just updated when doing day-to-day updates. You can use cvsed vp -M for doing that.
When doing doing non trivial changes, write meaningful commit massage such as remove obsolete tasks.

Advanced Info

to take out admin files
cvs checkout CVSROOT

to change an admin file
cvs commit cvswrappers

to checkout Zon V0.1.12 to zon_0_1_12 directory
cvs co -d zon_0_1_12 -r tag-0_1_12 wd

to add a binary:
cvs add -kb the_file
cvs commit the_file


to change an already committed ascii file to binary:
rm the_file
cvs admin -kb the_file
cvs update -A the_file


to change an already committed file that has -kk (or other keywords) to binary:
rm the_file
cvs up -kb the_file
cvs commit the_file


to branch a new version ('code freeze' for V1.0):
make sure everything is updated before tagging:
if the branch is from the main dev trunk, then: (this is the normal case)
cvs update -A -d
if the branch is from another branch, then:
cvs update -r branch-0_5 -d
add the tag to the repository:
cvs tag -c -b branch-1_0
cvs tag -c tag-1_0_0

now make the local copy use the tag:
cvs update -r branch-1_0

add a tag without a brach:
cvs tag -c tag-0_1_12

renaming a tag:
do not use tag use rtag, since tag does work on Attic files.
cvs rtag -r OLD_TAG NEW_TAG .zon/pkg/util
cvs rtag -d OLD_TAG .zon/pkg/util


renaming a branch tag:
On the repository itself perform the following:
for xx in `find . -type f` ; do rcs -nNEW_TAG:OLD_TAG $xx ; done
It should be done on the repository itself since "cvs admin -n" do not
perform the action on files in the Attic.
The last operation crated a new tag, now actually remove the old tag:
for xx in `find . -type f` ; do rcs -nOLD_TAG $xx ; done

search logs between dates in a specific branch into a file :
cvs log -Nd"01Jul2001<24Sep2001" -rbranch-10 > file_name 2>&1

listing the changes from date until date:
cvs log -d "8 days ago<0 days ago" * > changes.txt
now edit the file changes.txt and search for the word "revision " (the space is important)

updating a branch for a specific date and time:
cvs up -r branch-3_3 -D"2003-10-21 12:30"
This will NOT put a sticky date (see cvs stat) but will update the files on the branch for the specified date and time.

importing changes from a modified tree to a tree just checked out (without committing)
assume the product is named zon, then:
~/zon.mod$ cvs diff -c > mod.diff
~/zon.mod$ cd ..
~$ cvs co -d zon.new zon
~$ cd zon.new
~/zon.new$ patch -p0 -d . < ../zon.mod/mod.diff


NEVER use a pipe when doing cvs ci:
wanted to commit a lot of newly added files so
~$ cvs -q up | grep "^A " > x
went over x and saw that those are the files that should be commited
~$ cat x | xargs cvs ci
this is WRONG since a pipe is used before xargs. this pipe messes cvs ci up, since cvs ci exects to use stdin for vi for log message editing. The CORRECT way to do it is hence:
~$ cvs ci 'cat x'

Listing all available modules on remote CVS for checkout (cvs co):
~$ cvs -d :pserver:anoncvs@anoncvs.FreeBSD.org:/home/ncvs co -c
this particular CVS has many ports which are not included by default into checkout of FreeBSD itself.

changing a file to binary:
cvs admin -kb drawing.bmp

changing a file back to regular text:
cvs admin -kkv listing.txt

canceling keyword substitution, but leaving crlf expantion:
cvs admin -ko file.cmd

Real Life Examples

checking out a new copy of the dev tree:
cvs co -d src.dev wd

checking out a new copy of the v4.00 tree:
cvs co -d zon_1_0 -r branch-1_0 zon

creating a tag WITHOUT a branch:
c:\src.dev> cvs tag -c tag-1_0_1

move a tag for a certain file from one version to another (force):
cvs tag -c -F beta_qa-intel_ixp-15oct01-100-rel make_dist.sh

alternate more correct way to mark branches
tag the tree
cvs tag -c V_430
mark the branch point
cvs tag -c -b V_430_branch_yymmdd
or if you don't have a working copy
cvs rtag -c -b -r V_440 V_430_branch_yymmdd

creating V4.10 branch from dev tree:
make sure the files in dev are updated:
cvs update
create the V4.10 branch:
cvs tag -c -b V_410
checkout the V4.10 to be able to work on it:
cvs co -d src.410 -r V_410 zon

Merging Info

No need to do before/after tags for merges!
Use branch+date if there is no tags available.
revisions between which to merge can be referenced tags (either textual or numeric), both static and dynamic (branches). one can merge between dates on a branch where no static tags are available by using the ":" operator.
example: to merge change which occured on branch-20 between the beginning of july and the end of september of 2001 we need to use:
cvs up -kk -j branch-20:02-Jul-01 -j branch-20:01-Oct-01

merging branch fixes with dev:
first, tag the merge location:
src.dev$ cvs up -d -r V_432
src.dev$ cvs tag -c V_432_MERGE_2MAY00_DEV

now, get back to the dev tree:
src.dev$ cvs up -A -d add changes from branch (this example adds change from V_431 to V_432 to the dev branch)
src.dev$ cvs up -d -kk -j V_431_MERGE_4APR00_DEV -j V_432_MERGE_2MAY00_DEV
now solve conflicts, and check the modification in the files.
you can take a look at the list of changed files again using:
src.dev$ cvs up
you can take a look at the list of changes inside the files using:
src.dev$ cvs diff
now commit the changes:
src.dev$ cvs commit
the remark should note the parameters of the diff. e.g.: "merge from V_431_MERGE_4APR00_DEV till V_432_MERGE_2MAY00_DEV into dev"
Update merges.csv.

Releasing CVS Locks

If you get the following CVS lock:
cvs tag: [06:32:24] waiting for noam's lock in
/arch/cvs/rg/os/linux-2.4/arch/arm/boot/bootp

then telnet cvs, find the locks, kill the processes locking and remove the locks. You do not need to be super-user on cvs to remove the locks.

telnet cvs
fs$ cd /mnt/ram/cvslock/rg
fs$ find | grep "#cvs"
./os/linux-2.4/arch/m68k/sun3/#cvs.rfl.cvs.home.jungo.com.14392
fs$ ps auxw | grep 14392
\.\.\.
fs$ kill 14392
fs$ rm -rf os/linux-2.4/arch/m68k/sun3


If there are many locks, then you can do the following:
$ killall cvs
$ rm -rf /mnt/ram/cvslock/*


Notice that you will be killing all active CVS connections.

Creating a new branch or tag

Any tag/branch on CVS trees (e.g. rg, wd, uw, ut, project) should be documented in versions.csv. Virtually all tags are now created as soft-tags, which means committing them in versions.csv is all you need to do!!

Updating versions.csv: one of the following options:

  • Creating a new official WinDriver branch (V_620) or tag (R_622) should be done according to <ilya - please point to the relevant document!>
  • Creating a new official Hola branch (3.10.x branch or 3.10.4.1.x branch), or a new official Hola tag (3.10.4 or 3.10.4.1.6), should be done with zversion only! (see [1]).
  • Hola development branches for BIG features: if this development branch will have a long life time, and many developers will be working on it, and a lot of Bugzilla and QA work will be done on the branch, then consider opening it as a customer branch (see above).
  • any other tag/branch: use 'jcvs tag' for initial creation in versions.csv. After running 'jcvs tag', you can later return to versions.csv and chang any further settings as required - see explanations below.

Use of 'jcvs tag':
(Example: tag-4_7_11 on branch-4_7)
$ jcvs tag -v 4_7_11 -o branch-4_7 -m "product tag for 4.7.11" tag-4_7_11
(add -b for branches)
You can use the -n option (of jcvs, so it comes after jcvs) to prevent the changes from being committed to versions.csv.

Additional options:

  • -r DIR defines the repository location for which the tag applies.
    default: current location in tree (e.g. 'rg' when you're at the top of an RG CVS tree).
  • -bdesignates that this is a branch
  • -g mergeto - for branches only; designates the branch to which this branch will be auto-merged.
  • -t time of tag - default: NOW. If you want an earlier time, put the time of the last commit that applies to the tag you're adding.
    MAKE SURE TO USE UTC TIME (as it appears in 'CVS Search').
  • -h adds this as a hard-tag to CVS (come to yarony/derry first to explain why you need this!)
  • -f force - allows moving of existing tags.
  • -c MSG specifies the CVS commit message (default: same text given with -m)
  • -d display in Bugzilla - should usually be used only with tags/branches added using jversion, or for ST tags.
  • rtag used instead of 'tag', if you want to do the tagging on CVS without having a checked-out repository.

Please look further at the jcvs usage message for a full description of options to this command:
$ jcvs | grep -A25 "jcvs tag" Explanation of versions.csv fields:

  • symbol: name of symbol (tag or branch) as it appears in CVS
  • version: name of version as known by Hola users
  • repository: location in CVS repository.
    usually it is on top of one of our trees: ut, uw, wd, rg, etc. can be in lower points in trees for cases like vendor branches.
  • isbranch: is the symbol a branch ?
  • onsymbol: location point of symbol in CVS tree: either tag the the symbol was placed on, or parent branch.
  • owner: owner of branch (responsible for code on it)
  • creator: who actually created it
  • tag_date: when was the tagging done - in UTC (GMT) time. for soft tags you can put the time of the latest commit that this branch/tag is based on.
  • mergeto: for branches - what branch will this branch auto-merge into?
  • description: textual description
  • pl_owner: for customer branches/tags - the PL responsible for it. used by bugzilla to automatically assign R&D owner of bugs/enhancements, where this is applicable.
  • qa_owner: QA owner. used in customer branches to automatically determine QA owner for bugzilla issues.
  • soft_tag: is this a soft tag/branch?
    (should usually be 1, unless you have a good reason for using a hard-tag)
  • allow_manual_tag: should usually be 0, unless you have a VERY good reason for moving the tag on some files. usually it's better to just add a new tag in such cases.
  • allow_commit: allow commit in this symbol?
    should always be 0 for tags.
    for branches, it allows to close the branch for committing. generally only active branches should have this field set to 1.
  • display_in_bugzilla: is this a tag/branch we want to display in the Bugzilla versions tree and accept it in the version fields?

Diff files and ignore CVS keywords

Use the following diff command to exclude CVS directories and CVS keywords:

diff -uNbNr --exclude="CVS" --exclude=".dist" -I "\$Id\|\$Author\|\$Date\|\$Header\|\$Locker\|\$Log\|\$RCSfile\|\$Revision\|\$Source\|\$State" rg_dir/ rg_dir1/