Note: this page is only for general information. MINOS programmers should refer to this page for information specific to working with MINOS offline software CVS repository.

CVS tips

I recently built a personal CVS repository. Since others are interested in learning more about CVS, I will make some observations about my experience.


Prior to building a personal CVS repository I used the one at Indiana University (Lynn Miller maintains it), to get GMINOS code. I learned enough to do "cvs checkout" and "cvs update". I never did "cvs commit" with the Indiana CVS repository.

I felt at the time that to understand CVS better, one should make a personal repository and play with it (or at least make use of the experience of someone who had done so, with whom verbal contact was good). It took me a long time to actually do this. One reason was that I had read that AFS and CVS didn't coexist well (it was described as a conflict of the file locking philosophy). Since the only place I had to build a repository was on AFS disk space, this was a perceived inhibition. By asking the help desk, I learned that on FNALU this isn't a problem. Another holdup was that there is no sense in using CVS until one gets enough code in use, and being modified, that putting it into CVS has some attractiveness. A third holdup was that I never felt too comfortable with the documentation existing on the WWW. A final inhibition was that I thought it worth waiting for someone else to take the lead, and learn from that person.

Info Files

Key to deciding to go ahead and proceed in building a personal CVS repository was the realization that CVS is a FSF licensed product, and that CVS Info files probably exist (see comments in emacs document). These Info files I could use within Emacs, together with the Emacs interactive shell to give the commands and receive the standard output (Emacs has a CVS major mode which one can use, once a repository is set up--I haven't really explored that yet).

One recent complication with CVS Info files is that the latest version of CVS does not have them included with the distribution. They are therefore not to be found descending from the environmental variable CVS_DIR that results from "setup cvs". I had to reference back to an older version to access the info files. Fermilab's HelpDesk and the expert who was consulted about this don't plan to correct this situation; for them having HTML files explaining CVS is sufficient. As I state elsewhere in this little part of the Web, I regard the Info files as superior to the HTML files. Either can be produced from the original "texinfo" files that were distributed with the latest version of CVS.

Below I show how I access the CVS info files. The first line is inserted into my ~/.login file, to define the environmental variable CVS_INFO. The second line also goes in the ~/.login file and shows what I use to tell Emacs where to look for these "dir" files, and other info files (I added "~/emacs/info" to the standard list of places to look). The third line shows the entry in my local "dir" file-- that Info merges with the standard Emacs "dir" file.

setenv CVS_INFO `dirname $CVS_DIR`/v1_8_1_1/info

setenv INFOPATH $GEN2":~/emacs/info:/usr/local/lib/info/:/usr/local/info/:/usr/local/products/emacs/v19_30/info/"

* CVS: ($CVS_INFO/		        cvs

For the impatient, I should point out that the Info node "( CVS" is a reference menu for all the important commands--if one doesn't want to read the other stuff in ( See remark in my other writeup for a discussion of Info nodes.

Creating the Repository

The first step was to create a repository. "( a repository" says "See the instructions in the `INSTALL' file in the CVS distribution." This isn't very good advice (take my word for it--I tried it). "( up" gives better advice and gives the example

	cvs -d /usr/local/cvsroot init

I didn't save what I used to create my repository, so I can't give it as an example.

"(" suggests several ways to thereafter refer to the repository. I chose to define the `$CVSROOT' environment variable in my ".login" file.

"( a new project" suggests "the first thing you do when you start a new project should be to think through your file organization." This is very true. If you have existing files that you are going to want to put in the repository, they may be accompanied by other files that you don't want to put there. I used the "cvs import" command to do the initial load of the repository. It will start from the directory where it is at, and will import all files that aren't on the "ignore" list (for example, "*.o" files are ignored). This includes a recursive descent down through all the sub-directories. Before I did the initial import, I separated my Fortran files, Makefiles, and certain setup files into a directory structure that was not shared with all the other files I used to keep together with them (output files, for example).

Import into the Repository

Once the repository has its initial load from "cvs import", then it is best to rename the directory structure from where the import occurred, go up one level, and then do "cvs checkout".

In my case, the "cvs import" command looked like:

	cvs import -m "reconstructed phase I" gbeam phase_I phase_I

and was done from the "~wehmann/muon_studies/gbeam" directory. There were several sub-directories that were imported by the same command. An example of importing

First Checkout

The "cvs checkout" command looked like
	cvs checkout gbeam

This was done with the directory set to "~wehmann/muon_studies"; the earlier "gbeam" subdirectory had been renamed to something else (and is no longer needed, if the checkout is successful).

The "cvs checkout" command creates all the necessary directories. It also creates a special set of CVS files that keep track of where the checked out files came from. An Example of Checkout


As one modifies checked out files (local working copies), they diverge from what is in the repository. In the meantime, if the repository were being shared with other people, they could be "committing" changes to what is there. At any time, a "cvs update" can be done. This will reconcile what is in the repository with the local working files. Any real conflicts between the two get resolved by the user; they are first presented as "diff" output, and the user is expected to decide what to do to his local working files to resolve the conflicts with what other users have done. After a "cvs update", the user may do "cvs commit" to enter a record of his working files into the repository. An example of Committing

Remark on Tagging

CVS has other levels of complexity, such as "sticky tags" and parallel brances of development. The Info files explain these. The only thing I'll mention here is one experience that I had that I hadn't anticipated. I had done "cvs commit" several times, starting with the earliest versions of code that I had saved, so that I could mimic what I might have had in a repository if I had been using CVS all along--namely a progression of version changes. I had brought things up to the present, and had committed that code. I also "tagged it" with an appropriate name (with "cvs tag"). I then modified the code for some testing purposes--with the intent of going back later to the tagged version. I thought it would be sufficient to do "cvs update" from the tagged version, but I found out that this wasn't so. The safest thing to do is rename the directory structure to some other name, go up one directory, and do "cvs checkout" from the tagged version. More risky is to delete the working copies of files that differ between the two versions, and do "cvs update -r 'tag_name' filename" for each of the files deleted.

At the moment my disk area is cluttered with several relic versions of code. When I bump up against quota limits, and am confident of my CVS skills, then I can get rid of these relic versions.

I started a branch at one point, for some code modifications that I didn't want to have on the main development path. I used "cvs -b rtag" to start the branch. Being new at this, I managed to commit these modifications on the main development path as well. I could get back as working code a version of the code without these modifications, but I didn't find any way to commit the unmodified code back on the main development path without being forced to reconcile the unmodified version against the modified version that was at the head of the main development path. CVS forced me to do an update before the commit; the update combined the modified code with the unmodified code. Even with the import command this was true. I could import the unmodified code onto the "vendor" branch, but the local CVS files forced an update against the code at the head of the main development path, when trying to go from that branch back to the main development path.

The lesson I drew from this experience is to be more careful when branching off with a set of modifications. I suspect I should have used "cvs -b tag", rather than "cvs -b rtag". To know for sure, I'll have to wait for the next occasion to try branching.

Output I Saved

If it's of any use to anyone else, I kept a record of cvs output in "~wehmann/muon_studies/cvs". For a while I kept it as separate files for each command, but later decided to keep all output from one session in one file. Some of this output is shown in the examples. Later on I linked relevant files and directories to "~wehmann/misc/cvs"--so as to have it all together. I also started a "hints" file there, for things I'd like to remember quickly.

Shared GNUMI Repository

Scott Menary has been talking to Adam Para and the SDS people. The advice from that quarter is to set up the CVS repository for shared code on a Unix machine that does not allow interactive logins. Jobs are restricted on that machine such that users can only deal with the respository via CVS commands. Such a respository is planned for shared GNUMI code. Scott is first doing some work with the code itself, so that he has a better idea how to structure the repository. This is exactly the advice that the CVS Info files give--namely to give some real thought to how the files and directories should be organized before importing them into the repository.

Import Example

The files shown below were put by me into the directory "~wehmann/muon_studies/muon_new" and the "paw" subdirectory. Any files I didn't want imported into the CVS repository were moved to "~wehmann/muon_studies/muon_new_aux" and its subdirectories.
cvs import -m "reconstructed phase I" muon_new phase_I_muon_new phase_I_muon_new
cvs import -m "reconstructed phase I" muon_new phase_I_muon_new phase_I_muon_new
N muon_new/muon_new.setup
N muon_new/muon.ffr
N muon_new/Makefile
N muon_new/readmuonntup.F
N muon_new/uhinit.F
N muon_new/
N muon_new/Make.include
N muon_new/uload.F
N muon_new/get_mu.F
N muon_new/get_mu_init.F
N muon_new/look_cont.F
L muon_new/
cvs import: Importing /afs/
N muon_new/paw/rock.F

No conflicts created by this import

An Example of Checkout

After importing files into the CVS repository, they must be checked out in order to have local working copies that are being managed by CVS. In my case, in the example shown above (Import Example) I had imported from "~wehmann/muon_studies/muon_new" and its subdirectory "paw". Prior to doing the checkout, I renamed "muon_new" to something else and did "cd .." to get up to the "muon_studies" directory--prior to doing the checkout command shown below. The checkout command will create the necessary subdirectories.
cvs checkout muon_new
cvs checkout muon_new
cvs checkout: Updating muon_new
U muon_new/Make.include
U muon_new/Makefile
U muon_new/get_mu.F
U muon_new/get_mu_init.F
U muon_new/look_cont.F
U muon_new/muon.ffr
U muon_new/muon_new.setup
U muon_new/
U muon_new/readmuonntup.F
U muon_new/uhinit.F
U muon_new/uload.F
cvs checkout: Updating muon_new/paw
U muon_new/paw/rock.F

An Example of Committing

After the import shown above and checkout shown above, I changed my working files to reflect a later stage of development. I then wanted to record this change in the CVS repository. It was not necessary to do a "cvs update" first, since noone else is making changes to the repository.
cvs commit -m 'phase_II 1_20_save, muon_new'
cvs commit -m 'phase_II 1_20_save, muon_new'
cvs commit: Examining .
cvs commit: Examining paw
cvs commit: Committing .
Checking in muon.ffr;
new revision: 1.2; previous revision: 1.1
Checking in muon_new.setup;
new revision: 1.2; previous revision: 1.1
Checking in;
new revision: 1.2; previous revision: 1.1
Checking in readmuonntup.F;
new revision: 1.2; previous revision: 1.1
Checking in uhinit.F;
new revision: 1.2; previous revision: 1.1
cvs commit: Committing paw
Checking in paw/rock.F;
new revision: 1.2; previous revision: 1.1

Example of Creating a branch

I hesitate to put this in, for it may be confusing, but Adam wanted some examples. I'm treading on soft ground here, since I haven't done much of this. This example creates a branch with the tag "test_3_20 gbeam". It only does so for files in the directory having the tag "test_3_20_a". Present here is also an example of cvs log.

This branch was created for a test version of gbeam. After making the branch, I made the changes in my working files for the test version and commited them to the branch. I haven't yet gone back to the main trunk.

The output from "cvs log" shows the various symbolic names for revision numbers. The "1.1.1" indicates a "vendor" branch, used by the "cvs import" command. The "" is a branch revision number; this can be seen by the ".0.2" tacked on the end.

cvs rtag -b -r 'test_3_20_a' test_3_20 gbeam
cvs rtag: Tagging gbeam
cvs rtag: Tagging gbeam/adamoinc
cvs rtag: Tagging gbeam/adamoinc/from_gminos
cvs rtag: Tagging gbeam/inc
cvs rtag: Tagging gbeam/init
cvs rtag: Tagging gbeam/lib
cvs rtag: Tagging gbeam/subr
cvs rtag: Tagging gbeam/utilities
cvs rtag: Tagging gbeam/wbb
> cvs log gustep.F
cvs log gustep.F

RCS file: /afs/,v
Working file: gustep.F
head: 1.4
locks: strict
access list:
symbolic names:
	test_3_20_a: 1.4
	tag_3_21: 1.3
	tag_3_20: 1.3
	phase_I: 1.1.1
comment leader: "c "
keyword substitution: kv
total revisions: 5;	selected revisions: 5
revision 1.4
date: 1997/03/21 03:45:18;  author: wehmann;  state: Exp;  lines: +9 -4
put in test histogram for importance weighting
revision 1.3
date: 1997/03/16 20:50:33;  author: wehmann;  state: Exp;  lines: +49 -31
phase_IV, as of 3/16/97
revision 1.2
date: 1997/03/16 19:19:36;  author: wehmann;  state: Exp;  lines: +229 -177
phase_II 2_20_save files
revision 1.1
date: 1997/03/16 00:57:28;  author: wehmann;  state: Exp;
branches:  1.1.1;
Initial revision
date: 1997/03/16 00:57:28;  author: wehmann;  state: Exp;  lines: +0 -0
reconstructed phase I

Comments to: Alan Wehmann(
Last modified: Thursday, Dec. 4, 1997