Please send me comments/additions/questions about this tutorial. It needs more input from folks. Novices can help by pointing out confusing sections or by sending me questions not covered by this file. Masters can help by first verifying that the information here is sane, by sending their own tutorials, and by generally providing intelligent feedback.
Thanks, Gray Watson
It works by holding a central `repository' of the most recent version of the files. You may at any time create a personal copy of these files by `checking out' the files from the repository into one of your directories. If at a later date newer versions of the files are put in the repository, you can `update' your copy.
You may edit your copy of the files freely. If new versions of the files have been put in the repository in the meantime, doing an update merges the changes in the central copy into your copy.
When you are satisfied with the changes you have made in your copy of the files, you can `commit' them into the central repository.
When you are finally done with your personal copy of the files, you can `release' them and then remove them.
It can be that when you do an update, the changes in the central copy clash with changes you have made in your own copy. You will be warned of any files that contain clashes by a preceding C. Inside the files the clashes will be marked in the file surrounded by lines of the form <<<< and >>>>. You have to resolve the clashes in your copy by hand. After an update where there have been clashes, your original version of the file is saved as .#file.version.
If you feel you have messed up a file and wish to have CVS forget about your changes and go back to the version from the repository, delete the file and do an cvs update. CVS will announce that the file has been ``lost'' and will give you a fresh copy.
When you do a commit, if you haven't updated to the most recent version of the files, CVS tells you this; then you have to first update, resolve any possible clashes, and then redo the commit.
cvs add filename cvs remove filenameYou still have to do a commit after these commands to make the additions and removes actually take affect. You may make any number of new files in your copy of the repository, but they will not be committed to the central copy unless you do a cvs add.
CVS remove does not actually remove the files from the repository. It only removes them from the ``current list'' and puts the files in the CVS Attic. When another person checks out the module in the future they will not get the files that were removed. But if you ask for older versions that had the file before it was removed, the file will be checked out of the Attic.
If you wish to have CVS also remove the module sub-directory and your local copy of the files then your cvs release -d module.
NOTE: Take your time here. CVS will inform you of files that may have changed or it does not know about (watch for the ? lines) and then with ask you to confirm this action. Make sure you want to do this.
cvs log [filename(s)]
cvs diff [filename(s)]
One of the exciting features of CVS is its ability to mark all the files in a module at once with a symbolic name. You can say `this copy of my files is version 3'. And then later say `this file I am working on looked better in version 3 so check out the copy that I marked as version 3.'
Use cvs tag to tag the version of the files that you have checked out. You can then at a later date retrieve this version of the files with the tag.
cvs tag tag-name [filenames]Later you can do:
cvs co -r tag-name module
cvs rtag LIBRARY_2_0 libThis will recursively go through all the repository directories below lib and add the LIBRARY_2_0 tag to each file. This is one of the most useful features of CVS (IMHO). Use this feature if you about to release a copy of the files to the outside world or just want to mark a point in the developmental progression of the files.
cvs history -a -o shows you (a)ll the checked (o)ut modules cvs history -a -T reports (a)ll the r(T)ags for the modules cvs history -a -e reports (a)ll the information about (e)verything
setenv CVSROOT /src/masterfor tcsh/csh users, and
CVSROOT=/src/master; export CVSROOT
for bash/sh users.
Run the cvsinit script that comes with CVS to initialize the repository tree.
Encourage all your developers to make a working directory where they will be working on the files (mine is ~/src/work).
Edit the modules file to add the local modules. You can either do this by cd'ing to ${CVSROOT}/CVSROOT and saying co -l modules and then editing modules, or, better, cd to your working directory and do a cvs co modules (co is an alias for checkout).
Next add your modules to the file. I added the following lines to my file:
# libraries lib antaire/libdb antaire/lib/db dt antaire/lib/dt inc antaire/lib/inc lwp antaire/lib/lwp malloc antaire/lib/malloc inter antaire/lib/inter prt antaire/lib/inter/prt
The above entries now allow me to cvs co malloc to create a directory malloc where I am and check out the files from ${CVSROOT}/antaire/lib/malloc into that directory.
cvs co lib will check out all my libraries and make a whole tree under lib: lib/db/*, lib/dt/*, lib/inc/*, etc.
Next, create a cvsignore file in ${CVSROOT}/CVSROOT. This file contains the local files that you want CVS to ignore. If you have standard temporary files, or log files, etc. that you would never want CVS to notice then you need to create this file.
The first time you should go into the CVSROOT directory, edit the file and ci -u cvsignore to check it in.
You should apply the mkmodules.patch then recompile and install the mkmodules file See section A patch for mkmodules to make it know about cvsignore. Finally add the following line to your modules file (see above) so you can use CVS to edit the file in the future.
cvsignore -i mkmodules CVSROOT cvsignoreI have in my file:
*.t *.zip MAKE.LOG Makefile.dep a.out logfile ...CVS ignores a number of common temp files (*~, #*, RCS, SCCS, etc..) automatically. (see the manual entry for cvs(5)).
warning: CVS is good at this. Any files in the cvsignore file will be ignored completely without a single warning.
Now, add your files into their respective module directories:
cd into your current directory which holds the files. Build clean/clobber and make sure that only the files you want to be checked into the repository are in the current directory. Execute:
cvs import -m 'comment' repository vendortag releasetagThe comment is for you to document the module
The repository should be a path under ${CVSROOT}. My malloc library is checked into antaire/lib/malloc.
vendortag is a release tag that the vendor assigned to the files. If you are the vendor then put whatever you want there: (PRT_INITIAL, MALLOC_1_01, etc);
Releasetag is your local tag for this copy of the files. (PRT_1, malloc_1_01, etc);
I do cd ~/src/workExecute cvs co module where module is an entry from the modules file (see above):
Say cvs co malloc to get my malloc library. It will create the sub-directory malloc and will load the files into this new directory.
Edit the files to your heart's content.
If you add any new files to the directory that you want the repository to know about you need to do a
cvs add file1 [file2 ...]If you remove any files you need to do a
cvs remove file1 [file2 ...]If you rename you need to do a combination remove and then add.
Execute cvs update to pull in the changes from the repository that others made. It will resolve conflicts semi-automatically. It will tell you about the files it updates. U means updated, C means there was a conflict that it could not automatically resolve. You need to edit the file by hand, look for the <<<<< and >>>>> lines and figure out how the file should look.
Execute cvs commit inside the directory you checked out to papply your changes to the repository so others can use them (if they have the module in question checked out already, they need to do a cvs update to see your changes).
When you are done with the files (for the time being) you cd .. to the above directory and do a cvs release [-d] module-name which will check-in the files. The optional -d will remove the directory and files from your work directory when it is done releasing them. The release command will inform you if your made modifications to the files and if there are files it doesn't know about that you may have forgotten to add. watch for ? file lines printed. You may have to stop the release and commit or cvs add/remove the files.
WARNING: release -d is unrecoverable. Make sure that you take your time here. Fortunately, cvs release asks whether you really want to do this before doing anything.
To get more information, see the manual page man cvs for full (and much more complicated) details.
A basic knowledge of the Revision Control System (RCS) on which CVS is layered may also be of some assistance. see man co or man ci for more details.
With cvs tag malloc-1.0 you can give the symbolic tag malloc-1.0 to all the versions of the file in the malloc module. Later on, you can do cvs checkout -r malloc-1.0 malloc to retrieve the files that make up the 1.0 release of malloc. You can even do things like cvs diff -c -r malloc-1.0 -r malloc-1.5 to get a context diff of all files that have changed between release 1.0 and release 1.5!
CVS does not lock files. Instead, both you and Joe can edit alloc.c. The first one to check in it won't realize that the other have been editing it. (So if you are quicker than Joe you wont have any trouble at all). Poor Joe just have to do cvs update alloc.c to merge in your changes in his copy of the file. As long as you changing different sections of the file the merge is totally automatic. If you change the same lines you will have to resolve the conflicts manually.
find $CVSROOT -type d -exec chgrp src {} \; find $CVSROOT -type d -exec chmod 770 {} \;and (if available)
find $CVSROOT -type d -exec chmod g+s {} \;
cvs import -b 1.1.1 -m 'Malloc 1.01' MALLOC_1_01 malloc_1_01 cvs import -b 1.1.2 -m 'Malloc 1.02' MALLOC_1_02 malloc_1_02 cvs import -b 1.1.3 -m 'Malloc 1.03' MALLOC_1_03 malloc_1_03 cvs import -b 1.1.5 -m 'Malloc 1.05' MALLOC_1_05 malloc_1_05for each set of files? Are these sane incantations?
So keyword substitution must be prevented in binary files by added info to the rcs files for each binary file. I also prevent it in any files in which I don't plan to insert rcs keywords just to reduce checkout time. This can be done in the repository using the rcs command:
rcs -ko
rcs -c"// "
*** mkmodules.c~ Tue Mar 31 16:56:20 1992 --- mkmodules.c Sat Sep 19 14:30:19 1992 *************** *** 183,188 **** --- 183,202 ---- "a %s file can be used to configure 'cvs commit' checking", CVSROOTADM_COMMITINFO); (void) unlink_file (temp); + + /* + * Now, check out the "cvsignore" file, so that it is always up-to-date + * in the CVSROOT directory. + */ + make_tempfile (temp); + if (checkout_file (CVSROOTADM_IGNORE, temp) == 0) + rename_rcsfile (temp, CVSROOTADM_IGNORE); + else + error (0, 0, + "a %s file can be used to list files that cvs should ignore", + CVSROOTADM_IGNORE); + (void) unlink_file (temp); + return (0); }