CVS
General CVS Set Up
Make sure that this is in ~/.bashrc.
export CVSROOT=/home/chris/cvsroot
For remote CVS use, put these in the .bashrc:
export CVSROOT=:ext:xed@$XED/home/xed/cvsroot/
export CVS_RSH=ssh
Or you can do this:
cvs -d :ext:myuser@cvs.alab.example.edu:/cvsroot co mylilproject
Note
|
There is some question about whether there should be a colon
separating the host and the path on that host. It looks like it’s
optional. If you’re having trouble getting it to work, try adding it
(or taking it away if it’s there). On CVS 1.12.13-MirDebian-22 I
confirmed that it works with or without the colon. |
Source your .bashrc if echo $CVSROOT produces nothing.
$ . ~/.bashrc
Go to the repository.
$ cd $CVSROOT
Set it up while in the repository dir. Only do this once for a new place for CVS to store stuff.
$ cvs init
Go back to the directory you were interested in archiving.
$ cd -
Optional Check out the config CVS file to have a look This can go anywhere and you can make modifications to the config files that are stored by CVS. Do an update to make changes take effect.
$ cvs co CVSROOT
$ cvs release CVSROOT/
$ rm -r ./CVSROOT*
Start Using CVS On A Project - Directory Of All Good Files
Go to where the source code is. Here imagine that the source is being kept in a series of directories that get copied every week (a crude RCS).
$ cd ~/software/GeoGad.050423
Set up project (i.e. "module"). This must be done from the project’s directory. All files in the current directory will recursively be tracked. The module name is "GeoGad". Here "XedTech" is a "vendor tag". Here "START" is a "initial tag".
$ cvs import GeoGad XedTech START
After creating a module, the files involved have to be checked out before they can be properly used by CVS. This makes a new directory called GeoGad so you might have to go up a directory if you want to to have the CVS version repopulate the GeoGad directory you’re already in.
$ cd ..
$ cvs checkout GeoGad
Intend To Use CVS Before Writing Anything - No Files Exist
To set up a module in CVS before any source code is written, use any empty directory.
$ mkdir nothing
$ cd nothing
$ cvs import nova XedTech START
$ cd ..
$ rmdir nothing
Go to where you want to work on this project.
$ cd ~/funnewprojects
Get a CVS ready directory (called "nova") to work in.
$ cvs co nova
Change to this directory, create files and then "cvs add" them.
$ cd nova
Have A Nasty Untracked Mess - Some Files Good Some Bad
Imagine a project that’s a total mess, some files in the directory are backups done by hand and therefore shouldn’t be part of a CVS import. Start by moving the directory so that you can use this name for a new and improved CVS version:
$ mv /projects/jcsg/typical /projects/jcsg/typical.orig
Make a new empty version of the directory:
mkdir /projects/jcsg/typical
Go to that directory:
$ cd /projects/jcsg/typical
Copy in the files that need to be there; leave the bogus stuff.
$ cp ../typical.orig/wheelinvention.pl .
Make a CVS project out of it:
$ cvs import typical JCSG START
Make the source directory a working CVS directory:
$ cd ..
$ cvs co typical
Optionally delete the original directory:
$ rm -r ./typical.orig
Adding Files
To add files to the CVS module, set it up for addition and when a commit is done the file will be tracked too.
$ vi Makefile
$ cvs add Makefile
$ cvs commit
Deleting files from CVS’s control is similar to add.
$ rm planningnotes.txt
$ cvs delete planningnotes.txt
$ cvs commit
Before doing anything that might have been touched by other developers (or you from somewhere else), it’s important to make sure you are working with the latest versions. The -d will create any new files that don’t exist on your current version.
$ cvs update -d
Binary Files
If you need to add binary files (images, Word docs, etc.):
$ cvs add -kb logo.png
What if you forgot to mark it as binary? Try this:
$ cvs admin -kb icon.png
$ cvs update -A icon.png
$ cvs commit -m "make it binary" icon.png
Using CVS From A Remote System
Put this in the .bashrc (assumes $XED is defined as the IP#)
export XCVSROOT="xed@$XED:/home/xed/cvsroot"
Check out like this:
[catalyst][~/xfile/python]$ cvs -d $XCVSROOT co bildam
Renaming A File
CVS can be a bit unimpressive when trying to reorganize your files in a project. Simply renaming doesn’t have a concept in CVS. I need to do this quite a bit, so I wrote a script:
#!/bin/bash if [ -z "$1" ] then echo "Missing filename argument." exit -1 fi OLD=$1 # Make up your own renaming scheme here or use $2. NEW=_${OLD##SRC.}.hts mv ${OLD} ${NEW} cvs remove ${OLD} cvs add ${NEW} cvs ci -m "Renamed ${OLD} to ${NEW}" ${OLD} ${NEW}
If that’s not satisfying enough you can explore more tricksy techniques.
Renaming A CVS Project
If you start a project with a certain name, but later think of a better one, then you need to change the CVS name. There are other ways to do this, but this is pretty safe. Go to the CVSROOT directory where this project lives. Then make an exact copy to the new name:
cp -va jerkcontrol guestrelations
Go back to your working directory and:
cvs co guestrelations
Start using it. If everything is ok, then you can delete the old working directories and the old version in CVSROOT:
rm -r $CVSROOT/jerkcontrol
Note that there may be some references to the old project in the history file of $CVSROOT/CVSROOT.
Removing Stuff
To remove files, use the:
cvs remove file_to_stop_tracking
To remove a directory, make sure it’s empty, including removing all
the file using the cvs remove
command and then do and then use the
-P
option (prune) when updating or checking out again.
Note that CVS doesn’t really delete the directories. This is in case it needs to bring them back in some kind of rollback. This can be frustrating if you have a directory that really, really should be deleted. People report that just deleting the empty directory in the actual CVSROOT is ok. But this source seems to make me more cautious about that. I have used the harsh delete from the repository method and it does seem to work.
Timestamps
CVS seems to know when things are out of date and one would reasonably assume that it will work hard to preserve time stamps. Wrong! If you create a complex repository developed over time and then check out another copy of it elsewhere, the copy’s files will all have the date of the checkout. That’s very annoying. I had a project where I was relying on those time stamps. Fortunately, CVS does know when things were updated, but you have to ask it directly. Here’s what you can use:
cvs log ${FILE} | sed -n 0,/^date:/p | tail -n 1 | awk '{print $2}'
Or if you love sed:
cvs log ${FILE} | sed '/^date:/!d;s@^date: \([12][0-9/]*\) .*$@\1@' | sed q
Permissions
CVS does some half-assed stuff with permissions. It doesn’t just track
the state of the files as you set them in your checked out version.
No, it tends to keep the setting of the file that was originally
checked in. This can by very annoying. Apparently the only effective
way to change this is to go to the CVS server’s cvsroot and find the
project and go to the path/file of interest and change the
filename,v
file which corresponds to the wrongly permissioned file.
This can often require administrative privilege. Another way is to
cvs remove
the file and cvs add
it back with the correct
permissions. Of course you lose continuous history on that file. There
appears to be no
good answer.
CVS Keywords
The following keywords can be embedded in source code files and will get expanded into something more meaningful. The format is
$Keyword:$
Replace "Keyword" with one of these:
-
Author
-
Date
-
Header
-
Id
-
Log
-
Locker
-
Name
-
RCSfile
-
Revision
-
Source
-
State
Personally I use $Date:$
and $Revision:$
which seem the simplest and
most useful.
However, I’m starting to get the feeling that the idea of checking out a file that is not exactly the same as the one you checked in makes some people kind of uncomfortable. Mercurial only does keyword expansion through an unrecommended extension and Subversion is compatible with CVS but discourages automatic expansion. Maybe best to not base important functionality on this "feature".
General Usage
If you need to work on a project that is being tracked with CVS the general strategy is to go to the directory where you want your local copy of the project directory to live and do:
cvs co the_project_name
This should create a directory full of the latest version of the project. Next, you should edit the project or otherwise make your contribution. If you are adding files you need to do something like:
cvs add some_new_file
To let the rest of the development group know about your work, you need to check in your changes to the master repository. But before doing that, you should always update your current copy to see if any conflicts have arisen by anyone else concurrently working on it. Do:
cvs up
Note
|
If someone else creates a bunch of new directories, it is
possible that you will not see them with a cvs up . This can be very
puzzling and problematic. One solution to this is to back out to the
parent directory of the main CVS project directory and do a cvs co
the_project_name once again. This will update not just the files but
the new updated file structure too. Also try cvs up -d which seems
to work too. |
If there are conflicts with the update operation, you must resolve them some how.
If that goes cleanly then commit (or "check in") your work:
cvs ci -m "Provides an excuse to illustrate the update message."
Status Codes
When you check out a repository or update one, CVS often prints a single letter status code to indicate what the particular operation was all about. Those can be:
U |
updated (with a new version of the file) |
P |
patched (like U but with patches, not a whole new file) |
M |
modified (in your workspace, not in the repo) |
C |
conflict |
A |
added (but not committed) |
R |
removed (but not committed) |
? |
file is private to your workspace and not in repository |
Conflict
If two people work on the same file at roughly the same time (or one person just forgets to check in their work properly) you can wind up with a conflict. In most cases where the changes are possible to clearly sort out, CVS will make a new file containing both of the changes. This obviously happens when completely different parts of the file are modified. But if the exact same lines are changed by two different operations and then an attempt to check that in occurs, a conflict status arises.
When this happens, the unmodified version of the file is moved to
.#filename.revision
. In the normal file in the directory the
conflicted region is marked with <<<<<<<
and >>>>>>>
which denotes
what has been added and what has been removed. The two possibilities
are separated by a line of dashes. Just edit out the one you don’t
want and check it in. If you’re pretty sure you didn’t change anything
or you definitely want to defer to changes made elsewhere, then just
delete the file and do a cvs up
.
Troubleshooting
For reasons that are unclear, users were receiving the message:
cvs add: SomeUserFile added independently by second party
This wasn’t exactly true, but it was possible that typos or other mistakes were made. The file in question was not present in the repository. Rather it was in the cvsroot structure’s "Attic" directory. This normally is for branching. Basically there was no correct copy of this file in CVS. To get rid of what was there preventing the proper version from being added, the Attic file needed to be "merged" back in and then deleted. Something like the following was able to fix the problem:
cvs update -j 1.3 SomeUserFile
rm SomeUserFile
cvs remove SomeUserFile
cvs ci SomeUserFile
cp /home/${USER}/the_good_version/SomeUserFile .
cvs add SomeUserFile
cvs ci SomeUserFile
Don’t forget to use cvs log SomeUserFile
and see if the offending
file has a Attic
in its "RCS file" path.
SUBVERSION
Create A Repository
$ sudo mkdir /aleph1/svn $ sudo chmod 770 /aleph1/svn $ sudo svnadmin create /aleph1/svn $ sudo chgrp -R aleph1 /aleph1/svn $ sudo chmod -R g+rw /aleph1/svn/db /aleph1/svn/locks
Note- I did all of this already so normal users can jump right to the next step.
Creating A SVN Virtual Directory
SVN keeps track of stuff as if it was in a special file system. You can customize the contents of this file system. For example, you might want to start with a sub directory for all your projects:
$ svn mkdir file:///aleph1/svn/xed -m "Software that Chris is managing."
Committed revision 1.
$ svn ls file:///aleph1/svn/
xed/
And then you can start an empty project if you’re about to embark on one with no pre-existing files:
$ svn mkdir file:///aleph1/svn/xed/chnotify -m "Monitor the file system for changes."
$ svn co file:///aleph1/svn/xed/chnotify
$ ls -a chnotify
. .. .svn
Notice that you’ve created a directory in the virtual svn file system and then checked it out to a place in the real file system. Doing it in this way is important because now the directory in the real file system is trackable by Subversion as indicated by the existence of the .svn housekeeping directory.
Importing A Project
If you already have a bunch of files under development and want to begin tracking them all with svn, use the "svn import" command. This will take an existing directory tree and install it into Subversion management:
$ svn import -m "chnotify- Tracks file system changes" \
/home/xed/xfile/project/programming/bash/chnotify/ \
file://localhost/aleph1/svn/xed/chnotify
This does not make the existing directory understand Subversion, however. This just allows subversion to get some files. To have Subversion be able to care for files you can actually work with, you have to check the import back out.
Starting From Scratch and Adding Files
If you’ve started with the intent to use Subversion from before your project has any files, you need to add the files to the repository. Do this by:
$ vi chnotify.py
$ svn add chnotify.py -m "First sketch of program."
A chnotify.py
$ svn ci
Adding chnotify.py
Transmitting file data .
Committed revision 3.
The "svn add" tells Subversion that you want this file to be tracked. The "svn ci" commits your addition. Before doing the commit, someone else doing a checkout wouldn’t see this.
Checking Out A Project
$ svn co file:///aleph1/svn/xed/chnotify
Editing And Committing The Files
Change some things. For example:
$ vi libchnotify chnotify
Now that some files have been edited, it’s best to see if there are any conflicts, i.e. did some other user make the same changes while you did?
$ svn update
$ svn ci -m "Just some sample changes."
Using SVN Remotely With SSH
From the remote machine (for example, princeton):
$ svn co svn+ssh://lj/aleph1/svn/chnotify
(lj is a host alias for lajolla, see /etc/hosts)
Finding Log Info
Hopefully you’ve been in the good habit of describing your check ins with a little descriptive statement using "-m". That wouldn’t be very useful if you couldn’t do anything with that. Here’s how to review it: $ svn log chnotify.py