CVS (Current Versions System)
1. CVS Repository
General
format of CVS command
The general format of CVS command is:
% cvs [global options] command [options]
e.g. % cvs -Q update -p
1.1. Repository Location
There are two ways to tell CVS commands where the repository
is: the -d
option and the CVS_ROOT
environment variable.
With the -d
option, if the repository is on a local machine, the command would be
like:
% cvs -d /usr/local/cvs command
For remote repository, CVS provides a number of access
methods. The syntax is:
:method:user@server:directory
pserver
With the pserver access method, the login
command has to be run the first time the server is
accessed from a particular client machine. After a successful login,
the password is stored in .cvspass,
so subsequent cvs commands on the same machine won't require login. For
example,
% cvs -d :pserver:jwang@cvs.foo.com:/usr/local/cvs login
ext
Another commonly used method is ext, which uses an external connection
program such as rsh or ssh. The
actual program used is determined by the environment variable CVS_RSH.
For example, to use ssh,
% setenv CVS_RSH ssh
% cvs -d :ext:jwang@cvs.foo.com:/usr/local/cvs command
CVS_ROOT
If only one repository is used most of the time, then its location
could be set in the environment variable CVS_ROOT. The subsequent CVS
command doesn't need to specify the repository location. For example,
% setenv CVS_ROOT :pserver:jwang@cvs.foo.com:/usr/local/cvs
1.2. Create a Repository
1. Run the CVS init command
# cvs -d /usr/local/cvs_repo init
2. Create a UNIX group, e.g. cvs.
# pw groupadd cvs // on FreeBSD
3. Change the repository directory's ownership and permissions.
# cd /usr/local/cvs_repo
# chgrp -R cvs .
# chmod ug+rwx . CVSROOT
After these steps, any user in the cvs group can import files
into the repository.
2. Starting a New Project
Putting files into a CVS repository is called importing. The CVS
command is import:
% cvs import -m 「log msg」 projname vendortag releasetag
The import command will import the files in the current
directory and
the sub-directories. The projname
is the project's name inside the
repository. It is usually the same as the current directory name but
this is not a requirement. For example, to import the files in the
directory myproj,
% cd myproj
% cvs import -m 「initial import」 myproj jwang start
If the -m argument and the message is not present, CVS will
start an
editor for the user to enter a log message.
3. Checking Out a Working Copy
For example, to check out myproj
as imported above,
% cvs checkout myproj // or the short form
% cvs co myproj
This will create a directory called myproj, and get the latest versions
of all the files in that project.
To check out a project and put it into a directory with a different
name than the project name, use the -d
option:
% cvs co -d temp_proj myproj
This command checks out myproj
and put it in the directory temp_proj.
4. Update and Diff
The update command updates files in the working copy to a certain
revision, usually the latest. If the working copy has uncommitted
changes, CVS will try to merge the changes and detect any conflicts.
% cvs update // update all files
% cvs update file1 file2 // update specified files
The short form of update is up.
The diff
command compares files in the working directory to their
counterparts in the repository.
% cvs diff // compare all files
% cvs diff file1 file2 // compare specified files
CVS supports 「context-diff」:
% cvs diff -c file1 // context diff
Comparison can be made between any two revisions of the same
file.
% cvs diff -c -r 1.3 -r 1.4 file1 // comparerevision 1.3 and 1.4
// of file1
If only one revision is given, another will be the working
copy.
5. Committing
The commit
command sends changes of files to the repository and creates
new revisions.
% cvs commit -m 「a new feature」 // commit all files
% cvs commit -m 「a new feature」 file1 file2 //commit specified files
If log message is not present, CVS will start an editor for
the user to
enter a log message. The short form
for commit is ci.
6. Reverting Changes
Suppose a file file1
with a latest revision 1.9 needs to be reverted
back to 1.8. The user will need to create revision 1.10 that is exactly
the same as 1.8. The way to do it is to use the update command to get
1.8 and save it in the working directory and then commit it.
% cvs update -p -r 1.8 file1 > file1
% cvs ci -m 「revert to 1.8」 file1
The -p
option of the update command sends the file to stand output, so
it is redirected.
Another way to do it:
% cvs update -j 1.9 -j 1.8 file1 // merge the difference between
// 1.9 and 1.8 into file1
7. Adding and Removing Files and Directories
Adding
new files (2 steps)
%cvs add newfile
%cvs ci -m 「add newfile」 newfile
Adding
new directory (1 step)
% cvs add newdir
Removing
a file (3 steps)
% rm file1
% cvs remove file1
% cvs ci -m 「remove file1」 file1
Removing
a directory
First, remove all the files in the directory.
% rm file1 file2 file3
% cvs remove file1 file2 file3
% cvs ci -m 「remove all files」 file1 file2 file3
Then run update in the directory above it with -P flag that tells
update to 「prune」 empty directories.
% cd ..
% cvs update -P
Renaming
a file
% mv oldfile newfile
% cvs remove oldfile
% cvs add newfile
% cvs ci -m 「rename oldfile to newfile」 oldfile newfile
Renaming
a directory
% mkdir newdir
% cvs add newdir
% mv olddir/* newdir
% cd olddir
% cvs rm file1 file2 file3
% cd ../newdir
% cvs add file1 file2 file3
% cd ..
% cvs ci -m 「moved files from olddir to newdir」
% cvs update -P
8. Getting Snapshots by Dates and Tags
8.1. By Dates
This is done by passing update the -D flag. Dates have a number of
formats as follows. CVS uses the Universal Coordinated Time.
cvs update -D 「24 Aug 2004」
cvs update -D 「24 Aug 2004 12:34」
cvs update -D 「24/08/2004」
cvs update -D 「3 days ago」
cvs update -D 「24 Aug 2004 23:59:59 GMT」
Files checked out in the above manner will have a 「sticky date」, meaning these files cannot be modified and committed. To remove the sticky date, use update with the -A flag, which brings the working copy to the latest revisions:
% cvs -q update -A
8.2. Snapshots by Tags
A tag gives a label to a collection of revisions as a snapshot
of the
history of the repository.
To
create a tag
% cvs -q tag Version1_of_my_proj
The above command associates the name 「Version1_of_my_proj」
with the
snapshot represented by the working copy.
To
retrieve a snapshot
% cvs co -r Version1_of_my_proj myproj // check out a new copy
% cvs update -r Version1_of_my_proj // switch the working copy
//to the snapshot
In CVS, a tag can be used anywhere a revision number can be used. For
example,
% cvs diff -c -r Version1_of_my_proj hello.c
This command comparing the working copy of hello.c with the
revision
that's associated with the tag.
Snapshots checked out this way have a sticky tag which means the files
cannot be modified and committed. To remove the sticky tag, use update
with the -A flag.
9. Branches
Branches are created from a snapshot of the repository with
either the tag or the rtag command. The tag name will
serve as a label by which
the latest revisions of the branch can be retrieved.
Creating
a branch
One way to create a branch is to check out the version where the branch
is rooted, and then use the tag command to create the branch.
% cvs co -r Release1 myproj
% cvs tag -b Branch_Release1_bugfixes
To create a branch without checking out the base version, use the rtag
command:
% cvs rtag -b -r Release1 Branch_Release1_bugfixes myproj
This command achieves the same results as the above commands.
Merging
from branch to trunk
After making changes to the branch and committing the changes, if we
want to merge the change to the trunk, we can use the update command
with the -j option:
% cvs update -j Branch_Release1_bugfixes
% cvs ci -m 「merged changes from branch」
Suppose after the changes in the branch have been merged to the trunk, more changes are made and need to be merged again to the trunk, we only need to merge the difference since the last merge. This is achieved by using two -j options in the update command. Assuming the last change was tagged Release1_bugfixes_fix_1,
% cvs update -j Release1_bugfixes_fix_1 -j Branch_Release1_bugfixes