Quick Guide to CVS
A practical reference for setting up and using the Concurrent Versions System (CVS). Commands were originally tested on CVS 1.10. Covers setup, import, checkout, commit, branching, tags, and remote repositories.
Note: This guide was originally published in 2006 and has been updated in May 2026 with additional sections and improved formatting, with assistance from Claude (Anthropic).
CVS is a legacy tool. For new projects, Git is strongly recommended. This guide is useful for working with existing CVS repositories.
See Also — Other Quick Guides
Quick guide to n8n | Quick guide to NSCC ASPIRE2A | Quick guide to Docker | Quick guide to nawk | Quick guide to Emacs | Quick guide to GNUPlot | Quick guide to Git
Setup
Set the CVSROOT environment variable to point to your repository directory, then initialise it:
setenv CVSROOT ~/cvsroot # csh / tcsh export CVSROOT=~/cvsroot # bash cvs init # creates the repository structure
For remote repositories, CVSROOT takes the form :pserver:user@host:/path/to/repo. See the Remote Repositories section below.
Core Workflow
The typical day-to-day CVS cycle for a developer:
| Step | Command | What it does |
|---|---|---|
| 1. Get latest | cvs update | Pull changes from the repository into your working copy |
| 2. Edit files | your editor | Make your changes locally |
| 3. Review | cvs diff | See what you have changed before committing |
| 4. Commit | cvs commit -m "message" | Save your changes back to the repository |
Importing a Project
To place an existing directory of files under CVS control, cd into the project directory and run:
cd ~/project cvs import -m "Initial import" myproject vendor start
| Argument | Meaning |
|---|---|
myproject | Repository name — use this name in future checkout commands |
vendor | Vendor tag — can be any label (e.g. your username or organisation) |
start | Release tag — marks this as the initial release |
Checking Out a Project
Checkout creates a working copy of the repository in your current directory:
cvs checkout myproject # full checkout cvs checkout -r v1.2 myproject # checkout a specific tag cvs co myproject # shorthand
This creates a myproject/ directory. CVS metadata is stored in CVS/ subdirectories — do not delete or edit these.
Updating Your Working Copy
Run cvs update from inside your working copy to pull changes committed by others:
cvs update # update all files in current directory cvs update -d # also create any new directories added to repo cvs update file.c # update a single file
Status codes in the output:
| Code | Meaning |
|---|---|
U | File updated from repository |
M | File modified locally (your changes) |
C | Conflict — your changes clash with someone else’s; must be resolved manually |
? | File exists locally but is not tracked by CVS |
Committing Changes
After editing files, commit them back to the repository:
cvs commit -m "Fix off-by-one error in solver" # commit all changed files cvs commit -m "Update README" README.md # commit a specific file
If you omit -m, CVS opens an editor for your log message. To change which editor is used:
setenv EDITOR emacs # or vim, nano, etc.
Adding and Removing Files
Adding or removing a file is a two-step process: stage the change with add/remove, then make it permanent with commit:
# Add a new file cvs add newfile.c cvs commit -m "Add newfile.c" # Remove a file (delete it first, then remove from CVS) rm oldfile.c cvs remove oldfile.c cvs commit -m "Remove oldfile.c" # Add a binary file (prevents line-ending conversion) cvs add -kb image.png
To add an entire new directory: cvs add dirname followed by cvs add dirname/* and then commit.
Status and Diff
cvs status # show status of all files in working copy cvs status file.c # status of a specific file cvs diff # show all local changes as a unified diff cvs diff -u file.c # unified diff for one file cvs diff -r 1.3 -r 1.5 file.c # diff between two specific revisions
Always run cvs diff before committing to review exactly what will be saved.
Log and History
cvs log # full commit history for all files cvs log file.c # history for a specific file cvs log -r 1.3 file.c # log entry for revision 1.3 only cvs log -d "2006-01-01<2006-06-01" file.c # log within a date range
CVS uses dotted revision numbers (e.g. 1.1, 1.2, …) per file. Branch revisions use additional components (e.g. 1.2.2.1).
Tags and Branches
Tags
A tag marks the current state of all files with a symbolic name, useful for marking releases:
cvs tag v1_0_release # tag the current working copy state cvs rtag v1_0_release myproject # tag directly in the repository
Branches
Branches allow parallel lines of development, e.g. a maintenance branch alongside active development:
# Create a branch cvs tag -b MAINTENANCE_1_0 # Switch your working copy to that branch cvs update -r MAINTENANCE_1_0 # Switch back to the main trunk cvs update -A
Changes committed on a branch do not affect the main trunk. Merging branch changes back uses cvs update -j BRANCH_TAG.
Remote Repositories (pserver)
CVS can connect to a remote server over its own pserver protocol. Set CVSROOT to the remote path and log in once:
setenv CVSROOT :pserver:[email protected]:/srv/cvsroot cvs login # prompts for password; stored in ~/.cvspass cvs checkout myproject cvs logout # when done
SSH-tunnelled access is more secure for production use: set CVSROOT to :ext:username@host:/path and CVS_RSH=ssh.
Quick Command Reference
| Command | What it does |
|---|---|
cvs init | Initialise a new repository |
cvs import | Import a directory into CVS for the first time |
cvs checkout | Get a working copy from the repository |
cvs update | Pull latest changes from the repository |
cvs commit | Save local changes to the repository |
cvs add | Schedule a new file for addition (follow with commit) |
cvs remove | Schedule a file for removal (follow with commit) |
cvs status | Show the status of files in the working copy |
cvs diff | Show differences between local and repository versions |
cvs log | Show commit history and revision log |
cvs tag | Apply a symbolic tag to the current state |
cvs tag -b | Create a branch tag |
For a more comprehensive tutorial, see this CVS guide. For new projects, the Quick Guide to Git is a better starting point.
Share this:
- Share on X (Opens in new window) X
- Share on Facebook (Opens in new window) Facebook
- Print (Opens in new window) Print
- Email a link to a friend (Opens in new window) Email
- Share on LinkedIn (Opens in new window) LinkedIn
- Share on Reddit (Opens in new window) Reddit
- Share on Tumblr (Opens in new window) Tumblr
- Share on Threads (Opens in new window) Threads
- Share on Pinterest (Opens in new window) Pinterest
- Share on Telegram (Opens in new window) Telegram
- Share on WhatsApp (Opens in new window) WhatsApp
- Share on Bluesky (Opens in new window) Bluesky