CVS stands for Concurrent Version System. It is a
version control system that has been developed in the public domain by many people
beginning in 1986. Currently, CVS is maintained by Cyclic Software and there is lots of
information of their web site at http://www.cvshome.org/.
Using CVS, you can record the history of your source
files (normally text files, binary files are handled with some restrictions). Instead of
save every version of every file, CVS stores only the differences between the versions.
CVS also helps you if you are working in a group on the same project: CVS merges the work
when each developer has done its work.
Moreover, CVS allows you to isolate changes onto a
separate line of development, known as a branch. When you change files on a
branch, the changes do not appear on the main trunk. Later you can move the
changes from one branch to another branch (or the main trunk) by merging.
The CVS repository stores a complete copy of all
the files and directories which are under version control. Normally, you never access any
of the files in the repository directly. Instead, you use CVS commands to get your own
copy of the files into a working directory, and then work on that copy.
CVS can access a repository by a variety of means. It
might be on the local computer, or it might be on a computer across the room or across
the world. Using CVS with a remote repository we talk about client/server
operation. Several protocols are supported to connect to the remote repository, e.g.
rsh, password authentication, GSSAPI, kerberos.
You can define several repositories if you have
different development groups that work on separate projects without sharing any code. All
you have to do is to specify the appropriate repository when you are starting the
session.
If you want to keep track of a set of revisions
involving more than one file, you can use tags to give a symbolic name to a
certain revision of each file. You can think of the tag as a handle. When you pull on
that handle, you get all the tagged revisions.
file1 file2 file3
file4 file5
1.1
1.1
1.2 1.1
1.2 *** 1.1 *** 1.3 *** 1.2 *** 1.1 *** <*** tag ***>
1.3 1.2 1.4
1.5
So it's a good idea to tag every software release,
patch, or merge with its unique tag.
Often, two developers try to edit the same file
simultaneously. CVS supports some solutions for this situation, e.g.
- File locking or reserved checkouts: Only one person is allowed to
edit each file at a time.
- Use watches: Watched files are checked out read-only. To make them
read-write (and inform others watchers) the cvs edit command is used.
- Unreserved checkouts: The rarity of serious conflicts may be surprising, so
often neither file locks nor watches are used. If an overlap occurs, CVS prints a
warning and the resulting file includes both versions of the lines that overlap,
delimited by special markers.
Note: In some cases unreserved checkouts are clearly
inappropriate (e.g. if no merging tool exists).
3. A Sample Session
To learn the most used CVS commands, we are walking
through a typical work session. The commands are shown as CVS command line and over
WinCVS menus. Note that the most used WinCVS commands have short cuts or context
sensitive popup menus (by clicking the right mouse button).
The first thing you must set-up your CVS session. Set
your environment and login to the server.
CVS commands
Set $CVSROOT for local access...
> CVSROOT=<cvs_root>
> export CVSROOT
... or remote access and connect to the CVS
server:
>
CVSROOT=:pserver:<username>@<servername>:<cvs_root>
> export CVSROOT
> cvs login
WinCVS commands
Start your WinCVS client program. First time you must
set-up your preferences.
Admin -> Preferences -> General Settings
Admin -> Preferences -> Global Settings
Admin -> Preferences -> WinCVS Settings
Then you can login to the CVS server:
Admin -> Login
Remarks
The repository's root directory <cvs_root> is
defined either on the local server or on the remote server <servername>. After the
successful login, you are ready to work under CVS.
Next thing you must do is to get your own working copy
of the source. Change to your working directory and use the checkout command to do this
(option -r for read-only).
CVS commands
> cd <work_dir>
> cvs -r checkout <module>
WinCVS commands
Create -> Checkout module ...
Choose your working area
Choose your module
Use the default settings in
this example. By default, files are checked out as read-only.
Remarks
After the successful login, the sources of
<module> will be copied into your local working area <work_dir>.
<module> is either a valid module name or a relative path in the repository.
If you have already checked out the sources you can
update your working area with the newest checked-in files:
CVS commands
> cvs update
WinCVS commands
Select the <module> in the module tree, then the
menu Modify à Update selection...
Remarks
The default directory for the update command is always
the current working directory. The command updates the subdirectories recursively.
In this chapter we describe the normal way to edit a
source file using reserved checkout (file locking). Change to the working directory where
the file to edit exists.
CVS commands
> cd <work_subdir>
> cvs admin -l <filename>
> cvs update <filename>
> cvs edit <filename>
> vi <filename>
WinCVS commands
Select the file <filename> in the file list, then
the menus
- Trace -> Lock selection
- Modify -> Update selection ...
- Trace -> Edit
- Query -> View selection or View with <default_editor>
You have decided to make a new version of the file
<filename>. This will store your new file in the repository and make it available
to other developers. For the undo of changes see the next chapter.
CVS commands
> cvs commit -m "<log_message>"
<filename>
> cvs unedit <filename>
WinCVS commands
Select the file <filename> in the file list, then
the menu Modify -> Commit selection...
Commit settings, Enter the log message
The commit command
automatically unlocks the file <filename>. The unedit command is only successful if watches are in use. WinCVS also
automatically makes the file read-only.
You have decided to undo the changes of the file
<filename>. In this case, all the commands should be reverted. For the commit of
changes see the previous chapter.
CVS commands
> cvs unedit <filename>
> cvs update <filename>
> cvs admin -u <filename>
WinCVS commands
Select the file <filename> in the file list, then
the menus
- Trace -> Unedit selection
- Trace -> Unlock selection
You can finish your session with the cleanup of your
working area. Use the release command therefore. This command checks that all your
modifications have been committed.
CVS commands
> cd <work_dir>
> cvs release -d <module>
WinCVS commands
Select the <module> in the module tree, then the
menu Trace à Release selection.
Remarks
The -d option removes your working copy too. Otherwise
you can remove the working area manually.
4. Advanced Commands
In this chapter some further CVS commands are
described. This commands are very useful but not used in the daily business. Most of this
commands have a variety of options so we recommend to look up in [CVS] as well.
To add a new file to a directory, follow these
steps:
-
You must have a working copy of the directory.
-
Create the new file inside your working copy of the directory.
-
Use the command cvs add
<filename> to add this file to version control. For binary files use the option
-kb.
-
Use the command cvs commit
<filename> to actually check in the file into the repository. Other developers
cannot see the file until your perform this step.
You can also use the command cvs add to add a new directory as well. Note: Unlike most other
command the add command is not recursive.
New files are added, and old files disappear. But you
want to be able to retrieve an exact copy of old releases everytime.
Here is what you can do to remove a file:
-
Make sure that you have not made any uncommitted changes to the
file.
-
Remove the file from your working copy of the directory (use rm or
delete).
-
Use cvs remove <filename> to
tell CVS that you really want to delete the file.
-
User cvs commit <filename> to
actually perform the removal of the file form the repository.
Removing directories is similar to removing files: The
way that you remove a directory is to remove all the files in it. You don't remove the
directory itself. Instead you specify the option -P to cvs update, cvs checkout, or cvs
export, which will cause CVS to remove empty directories from working directories.
Tags are symbolic names to a certain revision of each
file. We recommend to tag all software releases, patches, or merges with its unique
tag.
You have two possibilities to tag: Running the
cvs tag command causes CVS to select the revisions which
are checked out in the current working directory. The cvs
rtag command works directly on the repository contents and requires no prior
checkout and does not look for a working directory.
Using the Working Directory
For the following cvs command tags the current working
directory.
CVS commands
> cd <work_dir>
> cvs tag -c <tag_name> [file | directory | module]
WinCVS commands
Select the module in the module tree or the file in the
file list, then the menu Modify -> Create a tag on selection...
Remarks
You can use the option -c to check for uncommitted
changes
(locally modified files).
Using the Repository
The cvs rtag command
tags the repository as of a certain date or time. This is useful to tag the latest
version. rtag works directly on the repository and
requires no prior checkout. This command is not supported by WinCVS. Tag the most recent
revision no later than <date> ...
> cvs rtag -f -D <date> <new_tag>
[file | directory | module]
... or tag those files that contain existing tag
<existing_tag>
> cvs rtag -f -r <existing_tag>
<new_tag>
[file | directory | module]
CVS allows you to isolate changes onto a separate line
of development, known as a branch. When you change files on a branch, those
changes do not appear on the main trunk.
Create a Branch
Again you will use the cvs tag or cvs rtag commands to
create a branch. The tag command uses the current revisions in the working copy, the rtag
command works directly in the repository:
> cvs tag –b <branch_tag>
... or tag those files that contain existing tag
<existing_tag>
> cvs rtag -f -r <existing_tag>
<branch_tag>
[file | directory | module]
Note that branches always get created in the
repository, not in the working copy. So you must checkout the branch files to your
working directory explicit:
> cvs -r checkout -r <branch_tag>
<module>
or switch the working directory to a given branch with
the cvs update command:
> cvs -r update -r <branch_tag>
<module>
Now you can work on the branch files and commit your
changes back to repository.
Merging a Branch
You can merge changes made on a branch into your
working copy. The working copy could be either the main trunk or another branch.
> cvs update -j <branch_tag> [file |
directory | module]
The option -j merges the changes made between up to the
newest revision on that branch into your working copy. Conflicts can result from the
merge operation. This conflicts should be resolved before committing the changes to the
repository.
If the development continuos on that branch, you may
want to merge those changes again. As recommended earlier each merged revision should be
tagged in the branch. Use that tag for subsequent merges:
> cvs update -j <merge_tag> -j
<branch_tag>
[file | directory | module]
The most common use for CVS is to store text files. If
you are willing to give up a few of CVS' abilities (such as display differences, merging
revisions), CVS can store binary files as well.
The -kb option
available in some CVS commands insures that neither line ending conversion nor keyword
expansion will be done. New files can be added as follows:
> cvs add -kb -m "A binary file"
<filename>
Or you can use the following commands to recover the
binary file:
> cvs admin -kb <filename>
> cvs update -A <filename>
> cvs commit -m "Make it binary" <filename>
CVS can use a mechanism known as keyword
substitution or keyword expansion to help identifying delivered files.
Embedded strings of the form $keyword$ in the source file are expanded to strings
of the form $keyword:value$.
This is a list of the keywords. For full explanation,
please refer to [CVS].
$Author$
|
The login name of user who checked
in the revision.
|
$Date$
|
Date and time (UTC) the revision was
checked in.
|
$Header$
|
A standard header.
|
$Id$
|
Same as $Header$ (except RCS file
without path).
|
$Name$
|
Tag name used to checkout this
file.
|
$Locker$
|
The login name of the user who
locked the revision.
|
$Log$
|
The log message supplied during
commit.
|
$RCSfile$
|
The name of the RCS file without a
path.
|
$Revision$
|
The revision number assigned to the
revision.
|
$Source$
|
The full pathname of the RCS
file.
|
$State$
|
The state assigned to the
revision.
|
5. Administrator Tasks
In this chapter some administrator tasks are discussed.
The directory $CVSROOT/CVSROOT contains some
administrative files. You can edit this files in the same way that you would edit any
other module: Get a working copy, edit it, and commit your changes in the normal way.
When you check in an administrative file, CVS rebuilds the administrative file
database.
The most important of the administrative files is the
modules file. It defines all modules in the repository. This is not strictly necessary,
but modules can be convenient in grouping together related files and directories.
Three different line formats are valid:
# key -a aliases...
# key [options] directory
# key [options] directory files...
This is a sample of modules file:
CVSROOT CVSROOT
modules CVSROOT modules
test projects/test1
One could write books about security issues... Here are
only some recommendations.
The directory $CVSROOT/CVSROOT contains
confidential information. You must control the permissions on this directory very
restrictive, specially if you are using the password authenticated server.
It is possible to grant read-only access to the repository using the
password authenticated server. There are two ways to do this: by inclusion and by
exclusion. Inclusion means listing all users with read-only access in the
$CVSROOT/CVSROOT/readers file. Exclusion means explicitly
listing everyone who has write access in the $CVSROOT/CVSROOT/writers file. Please refer to the following
rules:
-
If readers exists, and the user is
listed in it, then the user gets read-only access.
-
If writers exists, and the user is
not listed in it, then the user gets read-only access. This is true even if readers
exists, and the user is not listed in it.
-
If both files exist and the user is listed in them, CVS resolves
this conflict in a conservative way: such a user gets read-only access.
When authenticating a password, the server first checks for the user in
the file. If it finds the user, it will use that entry for authentication, else the
server can try to authenticate user name and password using the operating system's
identification (fall back behaviour). Please find further information in [CVS].
In a first step the files must be created in the
repository. The next step is to define the module in the modules file. This step is not strictly necessary, but modules can
be convenient in grouping together related files and directories.
Creating the Repository from Existing Files
You will probably already have several projects that
can be put under CVS control. In this case you will use the import command:
> cd <working_dir>
> cvs import -m "Imported sources"
<repository_dir> <vendor_tag> <release_tag>
The files in the working directory
<working_dir> are imported in the CVS repository as
$CVSROOT/<repository_dir>. <repository_dir> could contain a
directory structure as well.
It is a good idea to check that the permissions CVS
sets on the directories inside $CVSROOT are reasonable, and that they belong to
the proper groups.
If some of the files you want to import are binary, you
may want to use the wrappers features or to change them manually to binary.
Create an empty directory structure and import this
structure to create the corresponding directory structure in the repository. Then use the
add command to add files as they appear.
Check that the permissions CVS sets on the directories
inside $CVSROOT are reasonable.
Creating the Repository from Other Version Control Systems
If you have a project which you are maintaining with
another version control system, you may wish to put the files from that project into CVS
and preserve the revision history of the files. Here the way for RCS is shown, please see
[CVS] for other systems.
This is one of the few times when it is a good idea to
access the CVS repository directly: Create the appropriate directories in CVS if they do
not already exit. Then copy the files in the appropriate directories in the CVS
repository without changing the file name.
Note that the RCS files are not locked when you copy
them into CVS.
5.4 Backing Up the Repository
For the most part it is possible to backup the
repository just like any other files. However, there are a few issues to consider:
To get a consistent state of the repository, one should
not use CVS during backup. To not use CVS, you might forbid logins or turn off your CVS
server. Another idea is to lock CVS.
6. Examples
- Go to the top of the project tree: cd
/home/myproj
- cvs import -m "Initial Import into CVS" myproj akadia
start
myproj = Name under which you will check out the project
akadia = vendortag
start = releasetag
The directory tree in now imported in the CVS, however you must now
checking out a working copy, the current directory tree is still not a CVS working
copy.
- Go to another empty directory
Local Repository
- cvs checkout myproj
Remote Repository
- cvs -q -d
:pserver:zahn@rabbit.akadia.com:/opt/cvs-root \
checkout myproj
You get the same as what you imported, with the addition of a
subdirectory named CVS
- cd CVS (In the working CVS directory)
- ls -l
-rw-r--r-- 1 zahn dba 134 Aug 29 13:56 Entries
-rw-r--r-- 1 zahn dba 7 Aug 29 13:56 Repository
-rw-r--r-- 1 zahn dba 14 Aug 29 13:56 Root
- cat Repository
myproj
- cat Entries
/README.txt/1.1.1.1/Tue Aug 29 10:30:36 2000//
/hello.c/1.1.1.1/Tue Aug 29 10:30:36 2000//
D/a-subdir////
D/b-subdir////
D/myproj////
- cat Root
/opt/cvs-root
Make a change on hello.c, even if nothing in the repository has changed
since checkout, something in the working copy may have, and update will show that.
- cvs update
cvs update: Updating .
M hello.c
cvs update: Updating a-subdir
cvs update: Updating a-subdir/subsubdir
cvs update: Updating b-subdir
cvs update: Updating myproj
The M next to hello.c means the file has been modified. If
you want a more detailed look at the changes, you can get a full report in diff format.
- cvs diff
- cvs -Q diff (Shorter
Output)
- cvs -Q diff -c (Display some lines of context on
either side of a change)
The commit command send modifications to the
repository.
- cvs commit -m "Error corrected in explain()"
cvs commit: Examining .
cvs commit: Examining a-subdir
cvs commit: Examining a-subdir/subsubdir
cvs commit: Examining b-subdir
cvs commit: Examining myproj
Checking in hello.c;
/opt/cvs-root/myproj/hello.c,v <-- hello.c
new revision: 1.2; previous revision: 1.1
done
Check the status of the files in the CVS repository
- cvs status
Finding out who did what (Browsing Log Messages)
- cvs log
Create the new file in the working CVS directory, add and commit it in
CVS:
- cvs add newfile.c cvs server: use 'cvs
commit' to add this file permanently
- cvs ci -m "Added newfile.c" newfile.c
RCS file: /opt/cvs-root/myproj/newfile.c,v
done
Checking in newfile.c;
/opt/cvs-root/myproj/newfile.c,v <-- newfile.c
initial revision: 1.1
done
Unlike adding files, adding a new directory is done in one step:
- mkdir c-subdir
- cvs add c-subdir
Directory /opt/cvs-root/myproj/c-subdir added to the repositor
CVS handles CRLF correctly on textfiles, but this is not desired for
binary files, therefore use the -kb option. For Textfiles you may disable the keyword
expansion as well: use -ko.
cvs add -kb who
cvs ci -m "Binary File added" who
Removing a file is similar to adding one, except there's an extra step:
You have to remove the file from the working copy first.
rm newfile.c
cvs remove newfile.c
cvs ci -m "removed newfile.c" newfile.c
Removing newfile.c;
/opt/cvs-root/myproj/newfile.c,v <-- newfile.c
new revision: delete; previous revision: 1.1
done
CVS doesn't really keep directories under version control. If you want to
remove a directory from a project, you first remove all the files in it, then use update -P
to remove the directory from the working directory.
cd a-subdir
rm file1 file2 file3
cvs remove file1 file2 file3
cvs ci -m "Removed all files"
Now remove empty directory from working copy
cvs update -P
CVS does not automatically bring new directories from the repository into
your working copy. From time to time you should run update -d, telling to bring down any
new directories from the repository.
cvs update -d
All empty directories from the repository are now rebuild in the working
copy.
Renaming a file is equivalent to creating it under the new name and
removing the old file.
mv README.txt INSTALL.txt
cvs remove README.txt
cvs add INSTALL.txt
cvs ci -m "renamed README.txt to INSTALL.txt" README.txt INSTALL.tt
Removing README.txt;
/opt/cvs-root/myproj/README.txt,v <-- README.txt
new revision: delete; previous revision: 1.2
done
RCS file: /opt/cvs-root/myproj/INSTALL.txt,v
done
Checking in INSTALL.txt;
/opt/cvs-root/myproj/INSTALL.txt,v <-- INSTALL.txt
initial revision: 1.1
done
Renaming Directories is a bit cumbersome. The best policy is to try to
come up with a good layout when you initially import the project. One solution to rename
one or more directories is to checkout the project, make the changes on the local working
copy, delete the CVS project in the repository and import the changed project again.
cd myproj
mv a-subdir z-subdir
find . -name CVS -exec rm -rf {} \;
cd /opt/cvs-root
rm -rf myproj
cd /home/zahn/myproj
cvs import -m "Test Projekt" myproj akadia start
rm -r myproj
cvs checkout myproj
The date-based retrieval are done by passing update the -D flag. With the
-D option, update retrieves the highest revision of each file as of the given date and it
will revert the files in the working copy to prior revisions if necessary. Retrieving by
date is useful when the mere passage of time is your main concern.
cvs -q update -D "2000-09-14"
Often you really want to retrieve the project as it was at the time of a
specific event -- perhaps a public release, a known stable point in the software
development or the addition or removal of some major feature. The method CVS offers for
making such marks is known as tagging.
Setting a Tag (Snapshot):
cvs rtag Final-Release myproj
Retrieving the tagged release (Snapshot):
cvs checkout -P -r Final-Release myproj
Removing Tags (untagging)
cvs rtag -d Final-Release
myproj
|