Building Your First CVS Repository

In the second part of this three-part series covering the Concurrent Versions System (CVS), you will learn how to build your first repository. This article is excerpted from chapter two of Essential CVS, Second Edition, written by Jennifer Vesperman (O’Reilly; ISBN: 0596527039). Copyright © 2007 O’Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O’Reilly Media.

Building Your First Repository

CVS relies on a file-based database called the CVS repository. The repository contains all the historic data about your project, including each change that has been committed to the repository, as well as the user making each change. Your developers work from a sandbox which contains working copies of the files in your project. Changes from your sandbox (and other developer’s sandboxes) are committed to the repository, and changes in the repository but not in your sandbox are updated from the repository. Figure 2-3 shows a diagram of the relationship between a repository and sandboxes.

Figure 2-3.  Repository/sandbox relationship

The repository must be hosted on a machine with sufficient disk space to store your files and all the change data for your projects. The repository should be accessible to all the users from their workstations. Chapter 6 contains more information on choosing a repository server and setting up a more complex repository.

If the repository is on a remote computer, I recommend that users access the repository via SSH. Ensure that the server is running an SSH server and the workstations have a compatible SSH client. For more information on remote repositories and SSH, see “Accessing Remote Repositories” later in this chapter. Chapter 8 contains a full discussion of remote repositories.

For any one project, ensure there is enough disk space for three times the expected final size of that project. If you intend to store binary files, multiply by at least five. After your first project, you’ll have a feel for how much space to allow.

A repository can store many projects. If you are creating a repository that might handle several projects of unknown size, estimate as best you can and ensure that you can add more room later.

Not only can one repository store many projects, but one server can store many repositories. It’s usual for a server to have only a single repository, though.

A CVS repository is user data, and it should be on a partition that is backed up and won’t shut down the machine if it gets full. Repositories are often stored in /cvsroot, /var/lib/cvsroot, /home/cvsroot,or /usr/local/cvsroot. According to the Filesystem Hierarchy Standard (available at, the preferred location for a repository is /var/lib/cvsroot.

Another possibility is to put the repository in /cvsroot. This location is easiest for users to remember.

Example 2-5 illustrates the steps involved in creating a repository. First, create the repository root directory on the CVS server. In Example 2-5, I create the /var/lib/ cvsroot directory, and then install the security measures necessary to allow all users in the anthill group to write to the repository directories. (Ubuntu and Debian systems create the initial repository for you when the package is installed. You may need to add users to the default repository group, however.)

You must be root to work in the /var directory on most Unix, Linux, and Mac OS X systems. You can run a command as root on Ubuntu and Mac OS X by prefixing the command with sudo, as in sudo mkdir /var/lib/cvsroot. On other Linux and Unix systems, use the command su – to get a root shell first. A root shell is indicated with the # prompt.

Example 2-5. Creating a repository

$ su -
Password: ******
# mkdir /var/lib/cvsroot
# chgrp anthill /var/lib/cvsroot
# ls -la /var/lib
total 153
drwxr-xr-x      2 root   anthill    4096 Jun 28 16:31 cvsroot
# chmod g+srwx /var/lib/cvsroot
# ls -la /var/lib
total 153
drwxrwsr-x      2 root   anthill    4096 Jun 28 16:33 cvsroot
# cvs -d /var/lib/cvsroot init
# ls -la /var/lib
total 3
drwxrwsr-x      3 root   anthill    4096 Jun 28 16:56 cvsroot
# ls -la /var/lib/cvsroot
total 12
drwxrwsr-x      3 root   anthill    4096 Jun 28 16:56 .
drwxr-xr-x     10 root   staff      4096 Jun 28 16:35 ..
drwxrwsr-x      3 root   anthill    4096 Jun 28 16:56 CVSROOT
# chown -R cvs /var/lib/cvsroot

To allow others to use the repository, create a Unix group for CVS users (anthill in the preceding example) and chgrp the repository’s root directory to that group. You’ll need to add users to that group, using the appropriate command for your system (often gpasswd). Use chmod to set the directory’s SGID bit, so that files created in the directory have the same group ID as the directory’s group ID (this can prevent trouble later). You should also use chmod to set the directory group-writable, -readable, and -executable (you can do all your chmod work in one command with chmod g+srwx, as shown in Example 2-5).

To minimize security risks, create a user named cvs to own the repository and the administrative files. Use the –system option to adduser, so that cvs is created as a user who can never be logged into. chown the repository’s root directory and administrative files to that username. Chapter 6 explains security.

In OS X, you can use the niload command to add a user:

  $ sudo niload passwd . <<EOF  
  >username:*:701:20::0:0:New User:/Users/username:/bin/bash
  > EOF

Execute the following command to set up your chosen directory as a CVS repository:

  cvs -d repository_root_directory init

CVS commands follow the format:

  cvs [cvs-options] command [command-options]

The CVS options modify the behavior of CVS as a whole, and the command options modify the behavior of a CVS command. This format is explained more fully in Chapter 3.

Example 2-5 illustrates the entire process of creating a directory and then creating a CVS repository within that directory. In this case, the CVS option is -d repository_ path, and the command is init. There is no command option. anthill is the name of the group with access to CVS, and cvs is the name of the CVS owner.

Setting up the repository produces a place to store projects and also adds the special CVSROOT directory. The CVSROOT directory contains configuration and metadata files. Chapter 6 explains this directory in more detail. Projects are stored in subdirectories of the repository root directory, which is /var/lib/cvsroot in our example.

{mospagebreak title=Importing Projects}

When you have created a new repository, you may want to import your first project—a related collection of files stored under a single directory. It is possible to store a single file under CVS, but it will also be considered a project and you will need to store it under its own project directory. CVS groups things into projects because it needs to be able to create a subdirectory to store metadata about the project.

Your repository can hold one project, or it can hold many different projects. CVS scales well: a repository can help a single person with a small job to do, or can be used by a large company to provide version control to hundreds of separate groups.

Before loading a project into CVS, consider the project’s structure. If you move a file after it has been created and stored in CVS, CVS treats it as two files: the original in the original location and the new file in the new location. The history of the file is then split into two parts. Decide how you want to structure the source files for a project before you import it into CVS.

If you will eventually want to distribute your project’s files across several unrelated directories, it is best to develop the project under a single root directory, then distribute the files as part of the installation script. Chapter 7 describes the issue of project structure in more detail.

If you have binary files or other files that are not plain text, please see the information on binary files in Chapter 3 before adding them to the repository.

If you have any files or directories named CVS, please rename them before you import them—CVS restricts that name for its own purposes.

Create your initial project directory structure, possibly in /tmp. Once the project is stored in CVS, the repository backed up, and the backup verified, this initial version can be removed (which is one reason to use /tmp). You won’t be using it as a sandbox, and the project is duplicated in CVS, so there’s no reason to retain it once you have copies in the repository and its backup.

Once you have your initial structure, add any initial files you want. Change into the root directory of the project. Then, from within that directory, import the project with the command:

  cvs -d repository_path import name_of_project vendor_tag release_tag

If the repository is on the local machine, use the full path of the repository directory for the repository path. If the repository is on a remote server, see “Accessing Remote Repositories” for help on specifying the repository path.

For most cases, you will not need to know about vendor tags and release tags. CVS requires them to be present, but for now you can use the name of the project as the vendor tag and the current revision name as the release tag. These names must start with a letter and can contain only alphanumeric characters, underscores, and hyphens. See Example 2-6, which illustrates the process of creating a project structure and some project files, and then importing the project into CVS.

The vendor tag and release tag are explained in Chapter 7.

Example 2-6. Importing a project

/tmp$ mkdir example
/tmp$ touch example/file1
/tmp$ touch example/file2
/tmp$ cd example
cvs -d /var/lib/cvsroot import example example_project ver_0-1

After you run the commands in Example 2-6, CVS opens an editor window, shown in Figure 2-4. Enter a message to remind you what you intend this project to be.

The lines in the editor window that start with “CVS:” will not be included in the project’s history. The text displayed in the editor is configurable through the rcsinfo file described in Chapter 7.

The default editor for most Unix and Linux systems is vi. You need to type an i before inserting text; push the Esc key to return to the mode in which you can move the cursor around. The movement keys are the arrow keys, or h, j, k, and l. To save and exit, press the Esc key followed by :wq, then press Return. Chapter 3 explains how to change the editor to something other than vi.

After exiting from the editor, CVS completes the import, as shown in Example 2-7.

Figure 2-4.  Entering an import message

Example 2-7. Completing the import

N example/file1
N example/file2

No conflicts created by this import

In the repository, the imported project is stored as a collection of RCS format files. Example 2-8 shows the files for the project imported in Example 2-7. Note the ,v extension to the filenames—it signals that they’re RCS format files, and contain not only the file data, but also information about the files’ various changes over the life of the project.

Example 2-8. Repository contents

$ ls -la /var/lib/cvsroot
total 16
drwxrwsr-x     4 root    anthill    4096 Jun 28 17:06 .
drwxrwsr-x    10 root    staff      4096 Jun 28 16:35 ..
drwxrwsr-x     3 root    anthill    4096 Jun 28 16:56 CVSROOT
drwxrwsr-x     2 jenn    anthill    4096 Jun 28 17:09 example
$ ls -la /var/lib/cvsroot/example
total 16
drwxrwsr-x     2 jenn    anthill    4096 Jun 28 17:09 .
drwxrwsr-x     4 root    anthill    4096 Jun 28 17:06 ..
-r–r–r–     1 jenn    anthill     387 Jun 28 17:06 file1,v
-r–r–r–     1 jenn    anthill     387 Jun 28 17:06 file2,v

Figure 2-5 shows the same import done with gCVS.

Figure 2-5.  Importing a project

Once you’ve created your project, back up your CVS repository. You should continue to back up the repository periodically during your project’s lifetime. Once the repository has been backed up and the project verified, you can remove the original files. You need exclusive use of the repository when you do a backup, so do it at a time when you know other users won’t be committing changes.

Chapter 6 explains how to back up a repository and how to prevent others from making changes while you do so.

Before you do any work on the project, verify that the project is in CVS by checking out a sandbox (see “Checking Out Files” later in this chapter). Don’t try to use your original files as a sandbox. You must do any new work in files that you check out to a sandbox, which is why you can safely discard the originals. You should remove the original files to prevent yourself from accidentally modifying them instead of the files in a sandbox.

{mospagebreak title=Accessing Remote Repositories}

There are several ways to access a remote repository. This quickstart guide uses the ext method with the SSH protocol, but if your system administrator gives you different instructions, follow those. Chapter 8 explains the use of remote repositories in detail. The ext and SSH approach uses the ext repository access method, with an SSH client as the program that performs the connection. These are also explained in Chapter 8.

Your first step—at least, the first step that I recommend—is to install SSH on the client machine. Make sure that the client-end SSH protocol matches the server’s SSH protocol. Set up SSH keys or passwords and test the connection. Using SSH enables you to create a secure connection to the remote repository.

Next, if you’re on a Mac OS X, Unix, or Linux system, set the CVS_RSH environment variable on your client machine to the name of your SSH program; usually, this is ssh or ssh2. Graphical clients that support the ext and SSH approach may have ssh as an authentication type option in the dialog that requests the repository path. Check the documentation for your client.

In WinCVS and gCVS, call up the Preferences dialog under the Admin menu and select “ssh” as the Authentication method under the General tab. Under the Ports tab, you may need to enter the name of your SSH program in the option “Check for an alternate rsh name.”

In MacCVSX (for OS X), ssh is one of the authentication method options listed in the Preferences dialog. MacCVS for OS 9 and earlier versions do not support SSH as a standard option. Instead, you can make use of SSH from MacCVS via port tunnelling, as described in Appendix A.

If the repository is on the same machine as the client, the repository path is simply the full path to the repository’s root directory. On a remote machine, the repository path takes the form:


The method is the protocol used to connect to the repository. To use SSH, use ext as the method. Include the username and the at sign (@) if the username on the server differs from the username on the client. If you don’t have an SSH key on the host, the system asks you for a password when you try to log in.

The ext method doesn’t use the password or port portions of the repository path, and will ignore them if you include them. A full explanation of the repository path is given in Chapter 8.

Use the following command from your operating system prompt to run a CVS command against the remote repository:

  cvs -d repository_path command

For instance, Example 2-9 shows how to import a project into a remote CVS repository that is located on the host named cvs_server.

Example 2-9. Remote repository import

bash-2.05a$ cvs -d :ext:cvs_server:/var/lib/cvsroot import example no-vendor release-0
N example/file1
N example/file2
No conflicts created by this import

{mospagebreak title=Checking Out Files}

CVS stores projects and files in a central repository, but you work from a working copy, the sandbox, in your local directories. You create the sandbox with cvs checkout.

CVS creates the sandbox as a subdirectory of your current working directory. I like to create a directory to contain all my CVS sandboxes, and I use ~/cvs. Run this command from whichever directory you want a sandbox created in:

  cvs -d repository_path checkout project_name

It checks out all files for the named project. If your repository is on the local machine, the repository path is the full pathname of the CVS repository. If your repository is on a remote server, see the preceding section, “Accessing Remote Repositories.” Example 2-10 shows a local checkout.

Example 2-10. Local repository checkout

$ mkdir ~/cvs
$ cd ~/cvs
$ cvs -d /var/lib/cvsroot checkout example
cvs checkout: Updating example
U example/file1
U example/file2

The checkout command puts a copy of the project’s files and subdirectories into a directory named for the project, created in the current working directory. It also puts some administrative files of its own in a subdirectory of the project directory, called CVS.

You can check out an individual file or subdirectory of a project by replacing project_name with the pathname to the file or directory, from the project’s root directory. See Chapter 3 for more information.

CVS stores the repository path as part of the sandbox, so you should never again need to use -d repository_path in commands executed within that sandbox.

Note that the repository paths for local or remote checkout are the same as the repository paths for local and remote import. So if you used -d /var/lib/cvsroot for the import, you’d use the same for checkout.

If you are checking out a sandbox from a remote repository, the repository path must follow the remote repository format introduced in “Accessing Remote Repositories,” earlier in this chapter. Example 2-11 shows a checkout from a remote repository. Figure 2-6 shows the same checkout with gCVS.

Example 2-11. Remote repository checkout

$ cvs -d :ext:cvs_server:/var/lib/cvsroot checkout example
cvs checkout: Updating example
U example/file1
U example/file2

Figure 2-6.  Remote repository checkout with gCVS

Editing Files

Once you’ve checked out your project files into a sandbox, you can edit them with your favorite editor. Your sandbox is an ordinary set of files and directories, with an extra CVS subdirectory in each directory. Ignore the contents of the CVS subdirectory, and edit your project files as you normally would.

Some of CVS’s functions will not work properly in files with complex formats, such as image or sound files, and these files should be stored in binary format (see Chapter 3 for more information). The default save file format of editors such as Microsoft Word and doesn’t react well with the line-based diff system that CVS uses, and these files should also be stored in the repository as binary files, using the -kb option to cvs add (as explained in Chapter 3). However, if you save in plain-text, RTF, XML, or HTML format, you can commit them as normal CVS files.

Please check back next week for the conclusion of this article.

Google+ Comments

Google+ Comments