Table of Contents
Good places to look for more info than what's covered here
Basic Idea
Gotchas
Accessing Existing Repositories
Creating a Repository
Modifying Files in Existing Repositories
Other tips
Summary of examples
Additional examples without explanation
Good places to look for more info than what's covered here:
http://cvsbook.red-bean.com/cvsbook.html # Good tutorial (lengthy)
info cvs # Good reference
http://developer.gnome.org/tools/cvs.html # Gnome specific cvs tips
http://developer.gnome.org/doc/tutorials/import.html # Gnome specific importing
Basic Idea
In cvs, you work with a repository and one or more sandboxes. The
repository is the place where cvs stores all your files along with a
history of changes made to those files. The repository is usually
located under some directory on a remote machine, but it can be in a
directory on your local machine as well. A sandbox is simply a
snapshot of the files from the repository at a given moment in time.
Sandboxes don't contain any history of changes to files--they merely
contain a certain version of each file (well, with a little more
information, like the repository the files came from and the
specific version of each file currently in the sandbox). Day-to-day
work is done in a sandbox, with various cvs commands used to commit
changes to the repository or obtain updates made by others.
One makes use of cvs by running the cvs command with various
options. The basic syntax is:
cvs [global cvs options] [cvs sub-command options]
The main trick to learning cvs is to simply learn the most commonly
used cvs sub-commands (like 'add', 'commit', 'update') as well as a
few of the more common options for each.
Gotchas
CVS, unfortunately, has a handful of little gotchas or pitfalls that
can cause problems for new users. Most of this is due to historical
implementational issues combined with the need for
backward-compatibility. Other programs like Subversion are suppose
to fix these issues, but they aren't used as widely yet. The main
gotchas that I can think of are:
1) cvs doesn't handle binary files well
a) must mark each binary file as such
b) can't do incremental changes to binary files
2) one can't cleanly rename a file or move it to another directory
3) cvs treats files & directories differently
a) can't remove directories
b) special commands to deal with unused or new directories
4) cvs ignores file permissions
5) branching tags are different than normal tags
6) there seem to be a lot of abbreviations or alternate names for
various cvs sub-commands
7) you can't use subdirectories named 'CVS'
I'll address some of these issues here, for the rest, see the cvs
book at cvsbook.red-bean.com.
Accessing Existing Repositories
First, let me explain some of the global options to cvs:
Global CVS Options:
--help
-d [:access method:user@cvs.server.domain:]/location/of/cvs/repositories
Global CVS Options explained:
--help Prints help for the cvs command
-d Specifies the location of the repository that you are
trying to access (this option isn't required when you have
already checked out a sandbox and are working on it).
Valid access methods are pserver and ext.
Other useful Global commands that I occasionally use (which you may
want to read up on after finishing this tutorial):
-q
-Q
-z
As an example, I'll use the GNOME repositories, since they are
public and I'm familiar with them. To do so, you need
the following basic information:
access method: pserver
user: anonymous
cvs server: anoncvs.gnome.org
root directory: /cvs/gnome
With pservers, you first have to login. To do so, you use the login
cvs sub-command as follows:
cvs -d :pserver:anonymous@anoncvs.gnome.org:/cvs/gnome login
For the password, just hit enter without typing anything.
Next, we can checkout a module with the checkout sub-command. We
first have to know the names of the possible modules to choose from.
These tend to be on the web somewhere. For GNOME, you can find the
modules listed at
http://cvs.gnome.org/bonsai/rview.cgi?cvsroot=/cvs/gnome . We'll
checkout the module jhbuild. To do so, issue the following command
cvs -d :pserver:anonymous@anoncvs.gnome.org:/cvs/gnome checkout jhbuild
That will create a subdirectory called jhbuild below the current
directory and fill it. Change to that directory and have a look
around. Note in particular that each directory in a sandbox (other
than the ones named 'CVS') will have a CVS subdirectory for tracking
information about files within that directory. Make some changes to
a file (e.g. README) and then issue the following cvs command to get
a diff showing your changes:
cvs diff -u README
The -u option merely puts the diff in a readable format. Note that
you could get a list of all your changes in all files by running
cvs diff -u
You can also check for updates by running
cvs update -d
The -d option isn't necessary but is a good idea to always include.
Using it causes cvs to checkout any new sub-directories as well,
whereas without it, cvs won't.
Other useful cvs sub-commands I use often (you may want to read up
on these):
log
status
Other useful options for cvs sub-commands that I use often (again,
you may want to read up on these):
checkout -P, -d, -r
update -P, -r, -A
Creating a Repository
From the server (which for now, I'll assume is named
somemachine.com) which will hold the cvs repositories, you need to
first initialize the directory that will hold the repositories.
I'll assume that you want these to be located in /home/user/cvs. On
somemachine.com, run the following commands:
mkdir -p /home/user/cvs
cvs -d /home/user/cvs init
Now we have to import some project from a client (which for now,
I'll assume is named anothermachine.com) into the repository. We do
this from the machine that has the initial project, not from the
server (unless the two machines are the same). First, let's create
a new test project with a couple files to import. On
anothermachine.com, run the following commands:
mkdir project
cd project
ls /tmp > file_a.txt
ls -al . > file_b.txt
mkdir subdir
uptime > subdir/file_c.txt
Now, we'll be using the ext method for access, which basically means
ssh. Since CVS is old, it (stupidly) defaults to rsh instead of
ssh. So you first have to run the following (you may want to add
this to your .bash_profile):
export CVS_RSH=ssh
Now, import our new project to the server by running the following
command (make sure you're still in the project directory):
cvs -d :ext:user@somemachine.com:/home/user/cvs import -m \
"Initial import" project user start
If anothermachine.com and somemachine.com are the same machine, then
the above command could be shortened to:
cvs -d /home/user/cvs import -m "Initial import" project user start
In general, the syntax of an import (which must be launched from
within the directory that is being imported) is:
cvs -d import -m \
where the was described above under global
flags to cvs, the import message is any string you want, and the
vendor and release tags are basically unimportant (I've never used
them; I've even heard people suggest that you simply make up
something to use for those fields! Apparently some kind of advanced
use for them, though)
Now, importing project into cvs doesn't actually make the project
directory a real sandbox. To get a real sandbox, run the following:
cd ..
rm -rf project
cvs -d :ext:user@somemachine.com:/home/user/cvs checkout project
again, the last command above could be shortened to
cvs -d /home/user/cvs checkout project
if anothermachine.com and somemachine.com are the same.
Modifying Files in Existing Repositories
Let's start modifying the sandbox we have in the directory project.
Run the following commands on anothermachine.com:
cd project
cat file_b.txt | wc -l >> file_a.txt
touch file_d
echo "Hi there" >> subdir/file_c.txt
cvs -q update
As you can see, the update command shows that file_a.txt and
subdir/file_c.txt have been locally modified and that CVS doesn't
know anything about file_d (since it's new). We can commit the
changes for file_a.txt and file_c.txt by issuing the following
commands:
cvs commit -m "Added a line" file_a.txt
cvs commit -m "I added a polite message" subdir/file_c.txt
To commit the file_d change, though, we first have to add it to the
repository:
cvs add file_d
cvs commit -m "Initial creation" file_d
If we now checked for updates:
cvs -q update
we'd notice that everything was up to date and that CVS doesn't see
any local changes. Note that instead of the above individual
committing of changes, we could have simply added file_d and then
committed all files at once like this:
cvs add file_d
cvs commit -m "Made some random changes"
If you want to tag a specific version of your files, you use the cvs
tag command. An example:
cvs tag VERSION_1_0
note that tags cannot contain the '.' character, so underscores are
usually used instead. Users can than later obtain a certain release
of your files by using the -r flag to either the checkout or update
sub-commands.
Other tips:
If you want cvs update to ignore certain files, merely add the
filenames or wildcard patters to a file called .cvsignore in the
directory of interest. If you find yourself adding the same
wildcard patters to a .cvsignore file in every directory, moves
those patterns to your ~/.cvsignore file.
Summary of examples
cvs -d :pserver:anonymous@anoncvs.gnome.org:/cvs/gnome login
cvs -d :pserver:anonymous@anoncvs.gnome.org:/cvs/gnome checkout jhbuild
cvs diff -u README
cvs diff -u
cvs update -d
cvs -d /home/user/cvs init
cvs -d :ext:user@somemachine.com:/home/user/cvs import -m \
"Initial import" project user start
cvs -d :ext:user@somemachine.com:/home/user/cvs checkout project
cvs commit -m "Added a line" file_a.txt
cvs commit -m "Made some random changes"
cvs tag VERSION_1_0
Additional examples without explanation:
cvs -d :pserver:anonymous@anoncvs.gnome.org:/cvs/gnome \
checkout -d evolution-sandbox -r EVOLUTION_1_4_5 evolution
cd evolution-sandbox
cvs status ChangeLog
cvs status
cvs -q update -Pd -r evolution-1-4-branch
cvs status ChangeLog
cvs -Q update -Pd -A
cvs status ChangeLog
cvs log README
find . -type f | sed -e s%.*/%% | sed -e s/.*\\.// | sort | uniq
cvs -d /home/user/cvs import -m "Initial import into CVS" \
-W "*.doc -k 'b'" -W "*.pdf -k 'b'" -W "*.ps -k 'b'" \
project vendorname releasename
cvs tag -b stable-1_0-branch
cvs update -r stable-1_0-branch