Managing project files and directories with command line CVS

Releasing files and directories

At certain point in a project's development cycle, managing your project's source repository invariably involves dealing with files and directories that have become deprecated or obsolete. The decision is made to abandon a certain piece of functionality within a module, for example. Or perhaps a change in infrastructure demands getting rid of some files and moving others. This section deals with several methods for dealing with such file management issues in CVS.

Releasing refers to a way of designating certain directories or modules that will no longer to be used in the project. The command to release is invoked within a working copy and effectively cancels cvs checkouts for the designated directories and their files. Unless these are expressly deleted, the files and directories actually remain intact within the repository, including all file revision history, but are no longer included in when working copies are checked out.

The command to release a file or directory is:

cvs rel filename (or /directory_name)

More about releasing

Removing files

Removing is another way to get rid of files when you no longer want or need them to be part of the project's source repository. To do this, you must first delete the file from the working copy you have checked out on your local system.

Then, to remove a file from the shared repository, type:

cvs remove filename

After you have removed one or more files, you must commit your changes.

With "cvs remove" (or "cvs rm"), the old file is not completely eradicated but rather stored in the CVS "attic" along with its complete revision history.

Retrieving deleted files from a CVS repository

You can retrieve files that were version controlled and deleted from a CVS repository, by doing the following:

  1. Navigate to the working directory.
  2. Use the following command to retrieve the file to the working directory:

    cvs add [filename]

  3. Where "filename" could either be just a file name, or a path ending in the required file name.
  4. Do a "cvs commit" to commit the file added above to the repository.

Renaming and moving files and directories

If you have imported some existing source code into your repository, you may have files and directories you want to rename or move.

The best way to rename a file in your working copy involves a series of steps. Use:

cvs rm old_filename

to remove the old name, then

cvs add new_filename

and finally,

cvs commit new_filename

There really is no specific way in CVS to remove or rename directories. However, you can produce that effect by creating a new directory, moving the files you need into it, removing unwanted files from the old directory, and then simply no longer using it. Later, you can "prune" these empty directories the next time you check out a working copy by using:

cvs checkout -P

Another way to prune directories with no more files is to update with:

cvs update -dP

The CVS r* commands

The "cvs r*" commands are cvs sub-commands, that work directly on the CVS repository. The "cvs r*" commands are so called because they start with an "r." The following are the "cvs r*" commands:

  1. rtag
  2. rlog
  3. rdiff
  4. rannotate

Since the "cvs r*" commands work directly on the CVS repository, you don't need a working directory to use one. A "cvs r*" command would look like:

cvs [cvs-options] rcommand [rcommand-options] target

More about the "cvs r*" targets

The target of a "cvs r*" command is always a combination of the CVSROOT and a module name.

CVSROOT:

The CVSROOT value is a combination of protocol, user-name, server (name or IP address), and absolute path to the root of the CVS repository. The format would be:

:protocol:username@server:/path/to/cvs/repository

In CollabNet, this would typically look like:

:pserver:username@domainname:/cvs

There are two ways to input the CVSROOT to cvs. These are:

  1. Setting the environment variable CVSROOT to the CVSROOT value
  2. Using the "-d" option of the cvs command-line client.

Module name:

The module name is the specific CVS module, relative to the CVSROOT provided. In CollabNet, given a CVSROOT of:

:pserver:username@domainname:/cvs

The module name would be the name of a project.

For example, assuming the following:

server : bar.server.org

username : kid

projectname : foo

The CVSROOT would be:

:pserver:kid@bar.server.org/cvs

The module name would be:

foo

Note: Any subdirectory present inside a CVS module is considered a module too. So the module name could be extended to specifically address a sub-path inside the project. For example, if the project "bar" has a subdirectory "www," we could use a module name of "bar/www," to use a "cvs r*" command only on the "www" directory, of the "bar" project.

The CVS rannotate command

The "cvs rannotate" command displays information about every line in a committed revision of a file in the given repository module.

"cvs rannotate" is similar to the "cvs annotate" command, but works directly on the repository modules. In other words, you don't need a working directory to use the "cvs rannotate" command. The general usage of the "cvs rannotate" command is:

cvs rannotate target

Where "target" is of the form:

modulename[/filename]

Where "modulename" is the name a CVS module, relative to CVSROOT and "filename" is optional.

More about "cvs r*" targets

"cvs rannotate" produces a tabular output, showing the following information for every line, of every file, in the given module:

  1. Last revision affecting the line
  2. Author and date this line was last modified
  3. The actual line of text in the file

The complete command is:

cvs [-d :pserver:username@domainname:/cvs] rannotate [-r revision] [module...]

The CVS rtag command

The "cvs rtag" command adds a symbolic tag to a CVS repository module.

"cvs rtag" is similar to the "cvs tag" command, but works directly on the repository modules. In other words, you don't need a working directory to use the "cvs rtag" command. The general usage of the "cvs rtag" command is:

cvs rtag tagname target

Where "target" is of the form:

modulename[path/to/filename]

Where "modulename" is the name of a CVS module, relative to CVSROOT and "filename" is optional.

Note: rtag requires the CVSROOT of the repository, not the relative path. This is different from commands such as add and commit, which only require the relative path.

Where "tagname" is the name of the tag to be created.

The complete command is:

cvs -d: pserver:username@domainname:/cvs rtag tagname [module...]/path/to/cvs/repository

For more information about using the rtag command, see Open Source Development with CVS.

The CVS rdiff command

The "cvs rdiff" command displays the difference between two revisions, of the specified modules.

"cvs rdiff" is similar to the "cvs diff" command, but works directly on the repository modules. You don't need a working directory to use the "cvs rdiff" command. The general usage of the "cvs rdiff" command is:

cvs rdiff -r rev1 -r rev2 target

Where "rev1" and "rev2" are the revisions between which the diff is desired. If only one revision is specified, the second revision is assumed to be HEAD (the latest revision).

Where "target" is of the form:

modulename[/path/to/filename]

Where "modulename" is the name of a CVS module, relative to CVSROOT and "filename" is optional.

Note: rdiff requires the CVSROOT of the repository, not the relative path. This is different from commands such as add and commit, which only require the relative path.

More about "cvs r*" targets

Note: When specifying multiple files, the revision arguments must be symbolic tag names or branch names.

The complete command is:

cvs [-d :pserver:username@domainname:/cvs] rdiff -r revision [-r revision] [module...]

For more information about using the rdiff command, see Open Source Development with CVS.

More about "cvs r*" targets

The CVS rlog command

"cvs rlog" displays information about all the revisions, of the files in the specified CVS repository module(s).

"cvs rlog" is similar to the "cvs log" command, but works directly on the repository modules. In other words, you don't need a working directory to use the "cvs rlog" command. The general usage of the "cvs rlog" command is:

cvs rlog target

Where "target" is of the form:

modulename[/filename]

Where "modulename" is the name a CVS module, relative to CVSROOT and "filename" is optional.

More about "cvs r*" targets

The complete command is:

cvs -d :pserver:username@domainname:/cvs rlog [module...]

Importing existing code?

If you have existing files to add to the project, you can import these into CVS using the following command:

cvs import filename

Importing allows you to add a lot of files at once, something like a super "cvs add." To import all existing directories and files, in your top level directory type:

cvs import -m "log message" projectname

This creates the files and directories in the CVS repository for your project on this site. If you want to preserve these files and directories in their original state, you may want to tag or archive this set of original files before you or any other developers begin checking out working copies of project files.

If your existing files are already under versioning control -- either in another CVS repository or in a different versioning system such as RCS -- there is no automated method for importing existing files that retains file histories. Using the cvs import command, copying files over, or creating them as new files does not retain these histories.

CVS and RCS

If you're already familiar with RCS, both RCS and CVS use a similar format for storing the version control histories of individual files. But you should be aware of at least two critical differences in adapting CVS:

More about RCS and CVS

Tagging and branching

The CVS repository for your project hosted on this site supports branching and tagging your source files. At certain points in your project, you may want to enable development work in your project to progress in more than one direction simultaneously. Instead of maintaining a singular, linear path of development, CVS branching provides a way to divert or split the source tree for ancillary development activities without impacting progress of the project's primary effort. Examples of reasons to branch include:

Tagging is included in the discussion about branching because the two operations are used in conjunction. Tagging allows you to "take a snapshot" of the overall project's state at a certain point in time, for example, to preserve a build with some particular characteristic. Because CVS manages individual file revisions, tagging is an important option for benchmarking the overall state of project source code. Files included in a tag will most likely be at different points in their respective revision numbering.

The critical difference between branching and tagging is the reason they are complimentary operations:

Branching affects individual files' revision numbering, whereas tagging assigns a common identifying marker across all project files at a fixed point in time.

So, for example, project files are often tagged at the point where branches are created.

Ultimately, branches in your project with successful outcomes get incorporated or merged back in to the main development trunk. When that happens -- and it may occur repeatedly on large or long-term projects -- identifying the point where this merge occurs is another reason to create a tag.

To tag project files, type:

cvs tag unique_tag_name

Your tag name can be a release name or date, a product version identifier, or whatever you choose.

To create a branch, type:

cvs tag -b unique_tag_name

Branching and tagging are complex topics with many considerations and options. You can find more comprehensive information and instructions in the following resources:

Keyword substitution

Keyword substitution (a.k.a keyword expansion) is an RCS holdover that may be useful to you as a developer. Keywords essentially let you embed version information permanently in source files. A string containing the full version information associated with a particular keyword is substituted whenever the file is subsequently revised.

As an example, including:

$Author$

within the files permanently retains the username of the user who checked in that revision.

Keyword substitution is a method for tracking file versions once the files are no longer part of a CVS repository. Keyword substitution can also be configured and suppressed.

More about keywords (including a list of common keywords)

Top | Help index