1. Home
  2. Tutorials
  3. CVS
Yolinux.com Tutorial

CVS Intro, Commands and Examples

The Concurrent Versions System (CVS) is a Change Management (CM) system for software source code control to store and keep track of development changes.

CVS Intro:

CVS is primarily used as a source code control system for text files. Programmers will generate revisions to individual source code files. A collection of these files may define a specific software release. CVS aims to manage the collection of these files and the respective revisions of the individual files that make up the collection. CVS is a command driven file checkout, update, compare and management system. Front end web and desktop GUI systems are available to ease the use of CVS.

Setting up your environment for CVS:

  • Set environment variables: (add to your .bashrc file)

    Environment variables:

          export CVSROOT='/home/Project/CVS_root'     - directory for CVS source code repository
          export CVSEDITOR=/bin/vi
              

  • Set environment variables: (add to your .cshrc file) (for csh users)

    Environment variables:

          setenv CVSROOT  '/home/Project/CVS_root'
          setenv CVSEDITOR /bin/vi

  • CVSROOT: Location of CV source code repository.
Example use of CVS:

CVS commands are used with directives and command line options to create a repository, check-out, check-in and update code and interrogate changes between versions. Typically one will use a CVS repository which has already been generated, if not, one must be generated and populated with source code text files.

Creating CVS repository for the first time:

Create the CVS "root" of a new CM repository:
      cvs -d /home/Project/CVS_root init

-d: Directory used for repository. Note that an absolute pathname must be used.

[Potential Pitfall]: This is the CM repository and not a developer working area. No work, editing of files or changes should be made directly to this directory. The repository is loaded using the "import" command and files checked out to the users local working directory using cvs commands. Files are edited in the user's local working directory. Files are checked-in to synchronize and update the repository using cvs commands. Files are added and deleted using cvs commands. All interactions with the repository are done with cvs commands.

Importing a new project:

To put your project under CVS control:

Check in all files and directories from within the current working directory. The directory referenced is the tree structure for CVS not your current path.

      cvs import -m "Put text description here" ProgABC CorpABC start
The command notation is: import [-options] repositoryName vendortag releasetag

This will place the files and directories in your current working directory (and all recursively through the directory structure below the current), under CVS control. CorpABC is a "vendor tag". Start is a "release tag". The CM directory structure will be $CVSROOT/ProgABC/...

Now that it has been checked into the repository you can save,back-up or remove the current working directory. All future work will take place by checking out code from the repository. This check-out code will be under CVS CM control. The directory you just imported is not under CVS control.

Example:
      cd $HOME/src/ProgABCWorkingDir
      cvs import -m "Put text description here" ProgABC CorpABC start
The files and directories in $HOME/src/ProgABCWorkingDir were just checked into a repository named ProgABC. All exports and checkouts will start with the directory name ProgABC (not ProgABCWorkingDir). Use the same name for both if that is your intent.

[Potential Pitfall]: The directory you are importing can not be in the same directory as $CVSROOT. An endless recursive loop will take place as it will try and check-in the repository itself.

Export:

This is to get a copy of the sources and directories with the intent that the files will not be altered but shipped off site. Code extracted from CVS with export cannot be checked-in because export does not create any administrative entries.

A tag must be specified. Thus an original release would be extracted by:

      cvs export -r start ProgABC 
Start is the name of the first entry into CVS. See import. The directory ProgABC is generated with the contents of the export placed in that directory.

CVS commands and use:

By default CVS will apply recursively through sub-directories. Use the option flag "-l" to prevent this. The option "-R" explicitly defines the recursive behavior.

CVS command options: cvs [ cvs_options ] cvs_command [ command_options ] [ command_args ]

CVS OptionDescription
--allow-root=rootdirSpecify repository on the command line
-d cvs_root_directoryUse cvs_root_directory as the directory pathname of the repository. Overrides the $CVSROOT environment variable.
-e editor-commandUse the editor command specified for entering log information. Overrides $CVSEDITOR and $EDI‐ TOR environment variables.
-fDo not read the ~/.cvsrc file.
-HDisplay CVS command help
-nDo not make any changes to the root repository. Print out what would happen if the "-n" flag was not used.
-QQuiet mode. Less verbose than normal.
-qMarginally quiet mode. Reports of recursion are suppressed.
-vShow CVS software version and copyright information
-wMake new working files read-write. Overrides the setting of the $CVSREAD environment variable.

CVS Commands:

CVS OptionDescription
adminCVS interface to assorted administrative facilities.
annotateShows the revision modified each line of a file.
checkoutCheck out sources from the CVS repository for editing
commitCheck files into the CVS repository
diffShow file differences between revisions
exportExport sources from CVS. The files exported are NOT under CVS control. Note that files which are checked out are under CVS control. Use export to deliver or publich code.
historyShow status of files and users
importImport sources into CVS. Used for initial checkin of code into the CVS root repository.
logPrint out log information for files
lsUsed to list files and directories in the local working directory. Repository required.
rlsUsed to list files and directories in the repository.
rdiffGenerate "patch" format diffs between releases.
releaseIndicate that a Module is no longer in use. Cancels the effect of cvs checkout.
updateBring local work directory in sync with repository
addAdd file or directory to the repository
deleteDelete file or directory from the repository

Prints command flags used with CVS (Help):

      cvs -H 


Checkout:

      cvs co ProgABC
In this case, module "ProgABC" is a directory which will be created in your current directory with all the appropriate sub-directories and files.

The files/directories to checkout can be referred to by module name or relative path name from $CVSROOT.

To checkout a particular (previous) release or build:

      cvs co -r Rel-1A ProgABC
This will checkout the files necessary for the previous build for Rel-1A. The release or "tag" name in this example is "Rel-1A".

      cvs edit ProgABC/file.c

This pulls out a single file for editing without getting the whole project.

      cvs unedit ProgABC/file.c
Abandon work on file.

Note that all directories will contain a sub-directory named CVS/. This is for CVS CM management and should never be altered.

Command: cvs checkout [options] modules...

Checkout Command OptionDescription
-D dateUse the most recent revision no later than date. This option implies -P.
cvs checkout -D yesterday module-name
-lLocal; run only in current working directory.
-nDo not execute CVS command, just show what would be done if the flag "-n" was not used.
-PPrune (remove) empty directories in user working directory.
-RDefault behavior. Checkout directories recursively.
-r tag[:date]Checkout the revision specified by tag or, when date is specified and tag is a branch tag, the version from the branch tag as it existed on date. This option implies -P.
-d directoryCreate a directory called dir for the working files, instead of using the module name.
-cCopy the module file, sorted, to the standard output, instead of creating or modifying any files or directories in your working directory.
-sLike -c, but include the status of all modules, and sort it by the status string.
Other advanced options include: -f, -k, -p, -A, -j, -N


Update:

When working with a team of software developers, it is wise to periodically update your local working code to benefit from the changes and bug fixes contributed by other members of the team.

      cvs update -Pd 
This command updates the files and directories in the current directory and recursively through all sub-directories.

An update without the option "-Pd" will not add or delete directories in the local working directory when synchronizing with the root repository.

      cvs -qn update -Pd 
This command will show you the updates it is planning on making without performing the actual update. Your local files changed are also shown.

Command: cvs update [-ACdflPpR] [-I name] [-j rev [-j rev]] [-k kflag] [-r tag[:date] | -D date] [-W spec] files...

Update Command OptionDescription
-PPrune (delete/remove) all directories deleted in the root repository.
-dAdd any directory to your local working directory which has been added to the root repository.
-D dateUse the most recent revision no later than date.
-fOnly useful with the -D or -r flags. If no matching revision is found, retrieve the most recent revision.
-RDefault behavior. Update directories recursively.
-r tag[:date]Retrieve the revisions specified by tag or, when date is specified and tag is a branch tag, the version from the branch tag as it existed on date.
-lLocal; run only in current working directory.
-COverwrite locally modified files with clean copies from the repository (the modified file is saved in .#file.revision).
-I nameIgnore files whose names match name (in your working directory) during the update. More than one "-I" can be specified.
Other advanced options include: -k, -p, -A, -W, -j

Merge conflicts:

Merge conflicts occur when the following sequence of events occurs:
  1. you check out or update your code from CVS
  2. someone else checks in some changes to the code
  3. you make changes to text in the same line number as the other person's changes
  4. you perform an update - CVS shows that a conflict has occured! The same lines is a file have been altered by two people and CVS does not know how to update that file.

The cvs update will list all of the files recursively and list them prefixed with a single letter: M (modified), U (updated), A (added), C (conflict), etc. All files marked with a "C" are files with conflicts which require user resolution. Edit all files with conflicts.

Updates are marked in the file and you are obligated to edit the file and resolve the conflict or conflicts if multiple. The conflicting lines will be in the updated file. The changes of both people are marked in the file delimited by <<<<<<<, ======== and >>>>>>>.

Example file section showing the conflict:
    <<<<<<<  filename
      your uncommitted changes
      will appear first
    =======
      conflicting changes from the repository
      will appear here
    >>>>>>>  version number given here

Be sure to remove the <<<<<<<, ======== and >>>>>>> lines and alter the file so that it reflects your desires. Once the conflict has been resolved, the file will be ready to be checked in.


History / Status / Log:

Status of checked out working repository.
      cvs status [-v] ProgABC/file.c
OR cvs status [-v] ProgABC
Option "-v": Print tag information.

Review log of change history:
      cvs log file.c

Show local modifications to review what you may want to eventually check-in:
      cvs -qn update -Pd
All modifications in your local working directory will be shown with the prefix "M". Lists all files recursively from your current directory. While this is the "update" command, the command options "-qn" prevent an actual update.
CVS descriptors:
  • M: modified files in the local working directory. Use "cvs diff filename" to see your modifications.
  • C: conflict with repository. Modifications in your file "collide" with changes made and checked into the repository. This means that someone modified the same lines of code and CVS does not know how to merge your file with that in the repository because it does not know who is correct.
  • U: file updates have been made to the repository.
  • P: Like U, but the cvs server sends a patch instead of an entire file.
  • A: The file has been added to your private copy of the sources.
  • R: File has been removed
  • ?: File does not correspond to anything in the source repository

Command: cvs history [-report] [-flags] [-options args] [files...]

History Command OptionDescription
-lShow last modification only.
-D dateShow data since date.
-cReport on each time the repository was modified.
-eEverything (all record types).
-m moduleReport on a particular module.
-TReport on all tags.
-x typeShow records of a specified type:
  • F: release
  • O: checkout
  • E: export
  • T: rtag
  • C: merge with collisions
  • G: succesful merges
  • U: updated file from the repository
  • P: patched to match the repository
  • W: working copy of the file was deleted to match the root repository
  • A: file added
  • M: file modified
  • R: file removed
-oReport on checked-out modules (default behavior).
-aShow data for all users.
-wShow only the records for modifications done from the same working directory where history is executing.
-f fileShow data for a particular file. Multiple files can be specified on the command line.
-r revShow records referring to revisions since the revision or tag named rev.
-t tagShow records since tag tag was last added.
-u user-nameShow records for user user-name.
Other advanced options include: -b, -n, -p, -z


Check-in / Commit:

When done editing the files check-in (commit) your changes:

Check in files from within the directory. i.e. file.c must be in your current working directory.

      cvs ci file.c
            OR
      cvs ci -m "Put text description here" file.c
            OR
      cvs ci -m "Put text description here" ProgABC
The second check-in example will commit the entire module. (Files, directory structure and all)

Multiple files or directories can be checked in on the same command line. This is preferred if the files are all part of the same change set.

      cvs ci file1.c file2.c file3.c dira/file1.c dirb/file1.c

Cleanup and get rid of all the files:

      cvs release -d ProgABC 

The flag -d will delete all of your working sub-directories. CVS will let you know if files have changed and prompt you for a [y/n] reply.

Note that the cvs directives "ci" and "commit" are the same and perform the exact same function.

Command: cvs commit [-lnRf] [-m 'log_message' | -F file] [-r revision] [files...]

Check-in Command OptionDescription
-lLocal; run only in current working directory.
-RDefault behavior. Checkout directories recursively.
-r revisionCommit to revision. revision must be either a branch, or a revision on the main trunk that is higher than any existing revision number
-cRefuse to commit files unless the user has registered a valid edit on the file via cvs edit.
-F fileRead the log message from file, instead of invoking an editor.
-m "log message goes here"Use message as the log message, instead of invoking an editor.
-fForce cvs to commit a new revision even if you haven't made any changes to the file. Causes the -c and -R (default) options are ignored.
facilities.


Add/Delete files:

Add a new file to your project:
      cvs add file.c         
Multiple files can be specified on the command line:
      cvs add fileA.c fileB.c fileC.c        

Add a new directory "dirname/" and its files (and all sub-directories and files recursively), to your project:
      find dirname/ -type d \! -name CVS -exec cvs add {} \;
      find dirname/ \( -type d -name CVS -prune \) -o \( -type f -exec cvs add {} \; \)
      cvs commit -m "Programmer comments go here" dirname/

Note that if you specified a CVSEDITOR environment variable and no commit comments are added, the editor specified will pop-up for each and every directory to allow you to enter a check-in comment. CVS will get its commit/check-in comments.

Delete a file/directory from your project:

      cvs delete file.c         
The additions/deletions only fully take place after a check-in (commit) of the repository is performed.

Renaming a file:

      mv original-filename new-filename
      cvs delete original-filename
      cvs add new-filename
      cvs commit -m "Renamed file" original-filename new-filename


Modules:

The term "ProgABC" in our example is the name of a module as defined by the modules file found in CVSROOT/modules. To add a new module:
      cvs co CVSROOT/modules
cd CVSROOT
vi modules - Add module name and path to file

Then update changes:
      cvs ci -m "Add comments here" modules
cd ..
cvs release -d CVSROOT

The module "ProgABC" is a short name for "$CVSROOT/ProgABC"

Web cgi script cvsmodules to list all modules available for check-out.


Tagging a build/revision

Tag a revision such that the current build is known to be made up of particular releases of various files.

      cvs tag Rel-1A ProgABC 
Where Rel-1A is the tag name for the build of module "ProgABC"

Tag a repository (directory/module) to add the symbolic name to the "snapshot" of the current sources. Tag the repository before check-in.

If bug fixes are added afterwards, only those files which have been changed need be re-tagged.

To relocate a tag that already exists to a newer set of code:

      cvs tag -F Rel-1A ProgABC 


Diff:

      cvs diff file.c 
This will compare the version of the file in your working directory with that of the original you checked out.

The following will compare the two revisions of the file:

      cvs diff -r 1.1 -r 1.2 file.c 

The following will compare the two tagged versions of the file:

      cvs diff -r tag-a -r tag-b file.c 

Command: cvs diff [-lR] [-k kflag] [format_options] [(-r rev1[:date1] | -D date1) [-r rev2[:date2] | -D date2]] [files...]

Diff Command OptionDescription
-lLocal; run only in current working directory.
-RDefault behavior. Checkout directories recursively.
-r tag[:date]Compare with revision specified by tag or, when date is specified and tag is a branch tag, the version from the branch tag as it existed on date.
-D dateUse the most recent revision no later than date.
-linesShow lines (an integer) lines of context.
-aTreat all files as text and compare them line-by-line, even if they do not seem to be text.
-bIgnore trailing white space.
-BIgnore changes that just insert or delete blank lines.
--briefReport only whether the files differ, not the details of the differences.
--ignore-all-spaceIgnore white space when comparing lines.
--ignore-blank-linesIgnore changes that just insert or delete blank lines.
--ignore-caseIgnore changes in case; consider upper- and lower-case to be the same.
--side-by-sideUse the side by side output format.
-wIgnore white space when comparing lines.
Other advanced options include: -k, --binary, -c, -C, --context, --changed-group-format, -d, -e, --ed, --expand-tabs, -f, -F, --forward-ed, -H, --horizon-lines, -i, ...

The lines which are flagged as different are listed. Modern GUI diff tools are far superior and their use should be encouraged for complex changes. CVS diff can specify a GUI tool specifically: cvs diff -prog /usr/bin/tkdiff file.ext

List of graphical diff and merge tools:

  • tkdiff: [download] Comes with tkcvs CVS GUI front-end.
    Examples of CVS diffs with tkdiff: (See: tkdiff --help)
    • tkdiff old-URL@revA new-URL@revB
    • tkdiff -r457 -r459 file-name
    Note: Use command "svn log file-name" to view valid revision numbers for the file. Referencing invalid revision numbers as input to tkdiff will not work.
  • gtkdiff: Has diff3 and merge features. Written with GTK+. After gtkdiff-0.8.0, GNOME desktop required.
  • diffUse: Diff/merge GUI tool. Good line matching features. Supports Unicode.
  • kdiff3: Graphical directory and file diff, merge and edit. KDE3/Qt based. Supports drag and drop. Comes with S.u.S.E. distro. (Cross platform) MS/Windows download available. A very good directory and file diff and merge tool.
    • Difference: kdiff3 file1 file2
    • Difference: kdiff3 file1 file2 file3
    • Difference of two files: kdiff3 directory1/file directory2
    • Difference: kdiff3 directory1 directory2
    • Merge: kdiff3 directory1 directory2 -o dest-directory
    • Merge: kdiff3 file1 file2 -m
    • Merge: kdiff3 file1 file2 -o output-file
    • Diff with SVN: svn diff -r 457:459 --diff-cmd kdiff3 file-name
  • Kompare: Ships with (RHEL6/RHEL5/FC3+) KDE SDK. [manual]
    Included in Red Hat RPM package "kdesdk" an Ubuntu package "kompare".
    [Potential Pitfall]: RPM installation error:
    error: Failed dependencies:
            perl(DCOP) is needed by kdesdk-3.5.4-3.el5.i386 
    Solution: Install the dependency package "kdebindings".
  • mgdiff: Motif-based graphical file difference browser and merge. Comes with S.u.S.E. distro.
  • Meld: Compare, edit and merge.
  • xxdiff: Compare 2 or 3 files and merge. Also compares directories.
  • gvim and gvimdiff
  • Beyond Compare - commercial tool (cross platform)

The ~/.cvsrc configuration file:

The CVS user can generate a personal configuration file to customize default CVS behaviour by genrating a file .cvsrc in the user's home directory. This configuration file allows you to specify default command line arguments to CVS commands. For example:

File: $HOME/.cvsrc
checkout -P
update -P

This changes the behavior of a checkout and update. When performing the command "cvs update", the actual command performed will be "cvs update -P"

Note that "cvs co" and "cvs checkout" will both experience modified behavior.

Notes:

[Potential Pitfall]: If a file becomes locked and you need to remove the lock from the CVS repository remove the lock files. (files beginning with "#")

CVS over SSH:

This configuration uses a CVS repository on a remote server. One must set an additional environment variable and specify the remote location when using CVS commands. There are four methods available: (ext is generally preferred)

  1. EXT: (external connection)
    • Add the following to your ~/.bashrc file (client system):
            export CVS_RSH="ssh"
            export CVSROOT=':ext:user1@cvserver.megacorp.com:/home/Project/CVS_root'
            export CVSEDITOR=/bin/vi
                
    • Specify the remote "root":
      Example check-out (using the environment variable CVSROOT: cvs checkout ProgABC
      or specify on the command line: cvs -d :ext:user1@cvserver.megacorp.com:/home/Project/CVS_root checkout ProgABC
      where any cvs command and arguments can be specified (checkout used as an example)
  2. PSERVER: (password-authenticated server)
    Specify the remote "root" directory:
    Connect and authenticate: cvs -d :pserver:user1@cvserver.megacorp.com:/home/Project/CVS_root login
    You will then be asked for your password.
    Example check-out: cvs -d :pserver:user1@cvserver.megacorp.com:/home/Project/CVS_root checkout ProgABC
    [Potential Pitfall]: The password will be stored in ~/.cvspass and is a potential security hole. Be vigilant!
  3. KSERVER: (Kerberos security)
  4. GSERVER: (GSSAPI: Generic Security Services API)

Documentation:

Also see:

CVS GUI tkcvs:

TkCVS is a Tcl/Tk-based graphical front-end to CVS (and Subversion and RCS). It includes TkDiff for file diffs and merges. TkCVS is used for tagging, merging, importing, exporting, checking in/out, file query and status of CVS managed files.

Installation:

  • Ubuntu: sudo apt-get install tkcvs
  • Red Hat/Fedora/CentOS: rpm -ivh tkcvs-8.2.2-1.el6.rf.noarch.rpm
    This RPM is available from the EPEL (Extra Packages for Enterprise Linux) website.
    Requires tcl and tk.

Usage:

It is intuitive and easy to use. Start in your local working directory from the command line with the command: tkcvs

CVS GUI front-end tkcvs

tkdiff:

The CVS GUI tkcvs will invoke tkdiff to show file differences but it can also be invoked specifically for a diff from the command line:

Show file differences between the local working version of the file with that in the "HEAD" of the repository:

      tkdiff file.c 

Show file differences between the local working version of the file with that of the tagged version:

      tkdiff -r tagname file.c 

Links:

GUI Front-Ends to CVS:

Books:

"Open Source Development with CVS"
Karl Fogel
ISBN #158880173X, Coriolis Open Press.

The only book I know of which is totally dedicated to the topic of CVS.

Amazon.com