Most developers would use the following access info:
           setenv CVSROOT :pserver:$USER@cvs.astro.umd.edu:/home/cvsroot

CVS for CARMA/BIMA

CVS stands for "Concurrent Versions System", and helps a group of developers (or even a single developer on different computers) maintain source code (or even collaborative papers). Some of the most important features of CVS are: Here is a sample of CVS documentation: For BIMA-MIRIAD CVS access you do need to get a developers name (email: teuben@astro.umd.edu to get one), but read-only anonymous CVS access is also available (username: anonymous, no password needed)

Why should I use CVS, what does it buy me ?

Before we go and explain with some examples how you would probably use CVS, why use it? Sure, you have to learn a few new commands.... but what are the advantages. Here are some I find particularly useful:
  1. synchronizing your files with the central repository is just one command:
    	cvs update
    	
    and works heirarchically down through all your CVS enables directories. No more trying to find out which of your personal copies has the most recent file....
  2. CVS will warn you if a file is different from the official one
  3. two people can edit the same file (and often cvs can repair the difference, but that may also be a disadvantage)
  4. cvs allows you to have "other things" in your development tree, and will simply skip them when you "update" (receive new files from the archive) or "commit" (submit new files to the archive).
  5. branching, although complicated at first sight, is incredibly powerful
And the disadvantages?
  1. you have to discard your old messy source code tree(s), and install a new clean one
  2. CVS does not normally use file locking, so in principle files can be modified by two people (at different locations) at the same time. However, you can use locking, but it's extra cvs commands.
  3. deleting and moving files is a bit painful in CVS. So a project where the directory structure changes a lot may have to be restarted when the directory structure has stabilized.
Alternatives? Check out arch, OpenCM, subversion, BitKeeper, Mercurial, GIT, or if you want stick to CVS but turbo boosted, look at Meta-CVS. In July 2002 there was a Version Control System discussion on slashdot. In Febr 2004 O'Reilly discussed alternatives

CVS Server Setup and Usage

Normally you don't have to concern yourself with this, since supposedly others will have created a server for you. A CVS "server" can be located on a local disk, or accessible via the network (the latter the norm). Setting up your own reposity is however really very easy:
    setenv CVSROOT   /home/mycvsroot
    cvs -d $CVSROOT init
    
Using this repository is now the same (with the beforementioned $CVSROOT):
    cd /home/mycode/myproject
    make clean
    cvs import -d -m "testing 1 2 3" myproject vendor start
    cd ..
    mv myproject myproject.old
    cvs checkout myproject

CVS Client Setup and Usage

Setup

You would add the following environment variables to your C-shell environment:
   setenv CVSROOT   :pserver:$USER@cvs.astro.umd.edu:/home/cvsroot
   setenv CVSEDITOR emacs                       # or whichever editor you prefer
And you will also have to negotiate a password with the CVS maintainer (currently: teuben@astro.umd.edu) and tell him your $USER name of course. You can also download this perl script, which produces the encrypted passwd that you can safely send via email, or use the output of the following :
	perl -e 'print crypt("my_password","b6"), "\n";'

and you better not send me back the string "b60j72OwWnjlk"   :-)

   PLEASE NOTE THAT MacOSX USERS APPEAR TO HAVE TO USE TO USE A LOWER CASE PASSWORD

cvschroot allows you to edit your CVS/Root entries recursively. (you also need cvsu). You can probably find that under the "cvsutils" package on most linux distributions.

The very first time before you use this so-called "pserver" CVS access method, you need to logon:

   cvs login
This will maintain your password, encrypted, in a file in ~/.cvspass, so you will never get asked again. Sort of like the .ssh/authorized_keys file for automatic authenticated ssh usage.. Btw, you never have to do a logout from cvs (although the command does exist), unless you are worried somebody might steal your encrypted password. Hint: if you ever forget your password for a new machine, just copy the appropriate line from your ~/.cvspass file to that new machine.

If you want to start a new module in the CVS server, the following chain of commands gives an example of that:

    cd /home/user/myproject     ## this directory tree will be imported into CVS
    make clean                  ## or manually clean anything in this tree that should not be part of the CVS archive
    cvs import -d -m "some comment ...."   myproject vendor start           ## (see comment below)
    cd ..
    mv myproject myproject.old                                              ## myproject.old can be removed even
    cvs checkout myproject                                                  ## get a new sandbox
    cd myproject                ## now you are ready to edit/commit/update etc.etc.
Note that the "vendor start" is the CVS suggested method. The new module name, myproject, is preserved in this case, but you are free to choose any module name at that stage.

For existing modules, the first time you want to "checkout" the whole CVS miriad tree, do

   cd /opt		        ## or whereever you want to "root" miriad
   cvs checkout miriad          ## would create /opt/miriad and all below
now install miriad in fashion you normally do, from within /opt/miriad. You may notice a lot of CVS directories. Don't ever touch them, CVS uses them for administrative maintenance :-)

Usage Case 0: the CVS repository has changed location

Although very rare, if the CVS server has changed location, you will need to modify a few things on your local end(s). What is perhaps more common is that you need to change "CVS ownership" of your tree. E.g. you have a cvs read-only tree with anonymous as the user, but now have a pserver account and need to change the whole tree.

Usage Case 1: you have modified a file under CVS control, and need to submit it back

Assume you have modified a file and confirmed it still "compiles". You need to put this back in the CVS archive as follows:
  
   cd $MIR/src/prog/analysis
   cvs commit moment.for
As with all commit's, CVS will then throw you into an editor and urge you to add a line to describe why/what you have done. This information will go in the logfile, which is kept on a per-file basis (see the "cvs log" command).

Usage Case 2: synchronize your tree with the CVS archive version:

Now suppose you want to synchronize your version of MIRIAD with the official current state of the CVS archive version. So first you could check what has all changed:
  
   cd $MIR
   cvs -n -q update
and it will report a number of files, preceded with a single character code on their status:
  
	?	doesn't know the file in the archive, so will skip it
	U	file is newer in CVS, so you need to "update" it
        P       the same as P, except CVS would decide to path the file
		instead of updating the whole file. Great for slow links.
	M 	file is newer in your version, so you need to "commit" it
	C	there is a conflict :-)  You first need to "update" it,
		or "diff" it first, then study the resulting merge, and
		then "commit" it back to the archive. 
So, to sync your tree back with CVS, do:
  
   cvs update
or
  
   cvs update -d -P
if you want to be sure new directories are added (not done by default...) and empty directories are pruned.... This will report about all the patching going on to sync your tree. Note it will not mess with your modified (M) files, it will leave them alone. It's up to you to "commit" them when you're ready for that. For the conflict (C) cases, special care is needed of course, and I will write about that more later.

Usage Case 3: added a new file (or directory):

  
   cd $MIR/src/prog/analysis
   cvs add newmoment.for         <-- tag it to be added
   cvs commit newmoment.for	 <-- add the file physically to CVS now

   cvs add -kb picture.gif	 <-- tag it to be added, and as binary file

or for an already existing file to change it to binary

   cvs admin -kb picture.gif
   cvs update -A picture.gif     <-- but there is danger of bad cr/lf conversion
(note that binary files should add the -kb flag, to avoid interpreting some magic markers and cr/lf issues), for directories you can skip the commit step:
   cd $MIR/src/prog/
   mkdir atnf
   cvs add atnf

Usage Case 4: tell others you want to edit a file

Although CVS does not normally use locked files upon checkout, you can simulate this. The edit command will make a writeable version of the file in the CVS archive, and therefor warn others this file is being edited.
  
    cvs edit moment.for
    ....
    cvs commit moment.for
If you want to abandon you changes, simply do
  
    cvs unedit moment.for
An even more advanced method is to set a watch on the file. See the CVS manuals for more details.

Usage Case 5: removing a file from the archive

Removing a file is not just done with 'rm' of course. Since CVS maintains a full history, deleted files are actually moved to "the atttic". For example, to delete a file,
    rm badmoment.for
    cvs remove badmoment.for
    cvs commit badmoment.for

Usage Case 6: differencing files

A confusing thing is often when the "cvs diff" command is used, and no differences are found, even though you know that the repository has been updated. By default, "cvs diff" computes a difference of your current version with the version that YOU checked out last, not the one in the archive. So, here are the common usages of "cvs diff":
    cvs diff moment.for             <-- your local with your last checkout
    cvs diff -Dnow moment.for       <-- your local with last CVS archive

    cvs log moment.for              <-- revision history of this file
    cvs diff -r1.2 moment.for       <-- your local with archive version 1.2
By far the tkdiff (see also tkdiff home page) utility is more useful. It also knows about CVS, and the default usage
    tkdiff moment.for
    tkdiff -r1.12 moment.for
does the right thing, and present two colorful screen, side-by-side, of the CVS HEAD version with your local version. You can also use the usual -r1.2 flags to difference with an older CVS revision id. The following exceedingly simple shell script is actually quite useful to keep track of daily updates in a CVS tree:

#! /bin/csh -f
#
foreach file (`cvs -n -q update | grep ^U | awk '{print $2}'`)
  cvs log $file
  tkdiff $file
end

Usage Case 7: renaming a file

To rename a file, you would have to delete and add it again (but this would loose the direct CVS history of the file). You can also manually rename it, and edit the CVS administrative files in the CVS/Entries. However, the laborious way is:
    mv old.for new.for
    cvs remove old.for
    cvs commit -m "renamed  old.for to new.for" old.for
    cvs add new.for
    cvs commit -m "renamed  old.for to new.for" new.for

Usage Case 8: oops, my file was a binary data file

If you added a new file (see e.g. usage case 3), but later realized it was a binary file, you should make sure it did not get corrupted with the CR/LF problem and/or the CVS-key substitution.
    cvs admin -kb badfile
    cvs update -A badfile
For non-Unix system one would actually still have to check-in (commit) a correct brand-new version of the data, because of the CR/LF translations.

Usage Case 9: Adding a directory, with a few binary files inside

Here an example where you want to checkin binary files, hidden inside a directory:
    cvs add miriad_cube
    cvs add -kb miriad_cube/*
    cvs commit miriad_cube

Usage Case 10: I'm offline, what can i still do...

You should checkout the cvsutils package, using cvs itself of course:
   cvs -d :pserver:anonymous@cvs.red-bean.com:/usr/local/cvs login
   cvs -d :pserver:anonymous@cvs.red-bean.com:/usr/local/cvs co cvsutils
and read their documentation. In particular the before-mentioned cvsu and cvschroot commands are useful.

Usage Case 11: I broke some files after a certain date, how do I submit new versions:

Let's say a file is currently in revision 1.2 (use "cvs log" to find out the versions). You can get a local copy of an older version in several ways:
    cvs update -p -r 1.1 file1  >  file1
will get a local copy, you can edit that file and commit it again. You can probably also retrieve by date, if you prefer that, e.g.
    cvs update -p -D "25 August"  file1  >  file1
The problem is that all 1.1 -> 1.2 revisions are now lost in version 1.3

If however, you don't use the -p flag, a sticky flag will be set

    cvs update -r 1.1 file1 
and when you want to commit any edited revisions, you first need to remove the sticky flag with
    cvs update -A file1 
this will attempt to merge your local revisions with the CVS head, 1.2 in our example, and when you commit this it will become 1.3. This will thus include the 1.1 -> 1.2 revisions.

Usage Case 12: I forgot my pserver password....

First check if your entry in ~/.cvspass is something like
    :pserver:user_name@cvs.astro.umd.edu:/home/cvsroot Axy66s:q
where the last characters on the line is your encrypted password. If this looks right, you may have messed up someting else, so we need to make a new password. You then need to download the show_passwd.pl perl script, and make a new hash of the enrypted passwd, e.g.
    perl show_passwd.pl my_secret_password
    Hbgvfcr9kJP6Q
email me the encrypted one, and i will fix this. Alternatively, if you have another account with the correct .cvspass file, go there and copy that line into the one on your current machine. If that also fails, and I happen to be at 35,000ft, and you really need access to the code, use the anonymous account (it has no password, but is only read-only). You may also need to change the username on an existing sandbox, as described earlier using the cvsu utility.

Usage Case 13: I get all these messages about some sticky bit when trying to update or commit

Try the command
    cvs update -A
and it should fix that.

Usage Case 14: I can't seem to update a new directory

Try the command
    cvs update -d
you can also add, it forces checking new directories. It is normally not done, presumably for efficiency reasons.
    update -d -P
to your ~/.cvsrc file.

Usage Case 15: oh dear, somebody modified a file i had modified too...

You probably saw a C (for Conflict) when querying CVS (cvs -n -q update). Well, too bad, somebody beat you to it. Better communication is needed, or you should not have waited so long.... Basically it's a 4 step process:
    cvs update file         merge in the modified file
    tkdiff file              <-- in particular notice any <<< and >>> symbols
    emacs file
    cvs commit file
If that fails, or you don't care about your modifications and will do them later another way, remove yours (or the badly merged one) and checkin a new one:
    rm file
    cvs update file

Usage Case 16: I want to do branching....

here's a nice link: CVS branching and a short synopsis of the commands are:
     cvs tag -b TAG1                              # create a branch (from the top, or use rtag)
     cvs update -r TAG1                           # switch your sandbox to the new branch
     cvs checkout -r TAG1 -d proj_TAG1  proj      # or checkout a new branched version

     cvs update -j TAG1                           # merge a branch to mainline
     
     cvs commit                                   # commit them back to mainline
Although branching is very powerful, it is a somewhat more advanced usage of CVS. See also CVSLines, with a wizard program to manage branching.

Usage Case 17: ok, so i use windows....

so ok, you're in trouble. You could perhaps read Will O'Mullane's cvs and ssh on windows summary. If you haven't done so, you probably should install cygwin.

Another hairy issue with Windows (since Mac's now follow the unix convention) is the CR-LF nature of the end-of-line marker for text files. Although CVS deals with this transparantly, sharing files via SAMBA is now a no-no, and postscript files (which are supposed to be ascii) with embedded binary sections (legal in level 2 Postscript) can also be a big nuisance.

Usage Case 18: I want to clean my CVS directory and maybe create a patch file

If you want to make sure your CVS tree is clean of all junk you, or the installation software, has created, here's a recipe:
         cvs up -dPC
but if you want to create a patch file, that you can pass on to another CVS repository, do this:
         cvs diff -u > /tmp/test1.patch
after which this can be applied to another fresh (or even modified) tree:
         cat /tmp/test1.patch | patch -p0
assuming you were in the root directory of the project. Great way to bypass CVS if you don't want these changes to appear in CVS yet.

Usage Case 99: I type 'cvs', and it says 'command not found' ...

Yes, this is a sad case... nobody installed CVS for you. Visit the CVS home page or get the latest tar ball, e.g.
	wget http://ftp.gnu.org/non-gnu/cvs/source/stable/1.11.23/cvs-1.11.23.tar.gz 
	tar zxf cvs-1.11.23.tar.gz
	cd cvs-1.11.23
	./configure
	make
	make install
at which point the CVS software should be installed in /usr/local/bin. Obviously you'll need to be root for this. (April 2002: one problem we had is during the make, compilation complained about a missing krb5.h file. This seems like a configure bug; to fix it edit config.h and comment out the HAVE_GSSAPI line near the bottom and make again).
Page last modified: Friday, 02-Dec-2011 11:26:10 EST.