DaCoPAn Software Engeneering Project

- Home  - Overview  - Members  - Documentation 

- Resources/Links - Project Website

 

CVS basic commands guide

Invoking CVS

When you invoke CVS, you must specify which action you want to perform.

cvs command

Both CVS and the command can take options. Options that affect the behavior of CVS, independently of the command being run, are called global options; command-specific options are just called command options. Global options always go to the left of the command; command options, to its right. So in

cvs -Q update -p

-Q is a global option, and -p is a command option

Accessing A Repository

For this project follow the instructions covered in the TWiki topic HowToUseCVS

Checking Out A Working Copy

cvs checkout myproj
cvs checkout: Updating myproj
U myproj/README.txt
U myproj/hello.c

Behold - your first working copy! Its contents are exactly the same as what you imported, with the addition of a subdirectory named "CVS". That's where CVS stores version control information. Actually, each directory in the project has a CVS subdirectory. Your project can never contain subdirectories of its own named CVS.

Making A Change

Let's make the first change to the project since importing it (checking it out). To do this just edit the file you want to change locally in your machine.

Committing

The commit command sends modifications to the repository. If you don't name any files, a commit will send all changes to the repository; otherwise, you can pass the names of one or more files to be committed (other files would be ignored, in that case).

For example commit a specific file:

cvs commit -m "print goodbye too" hello.c
Checking in hello.c;
/usr/local/cvs/myproj/hello.c,v  <--  hello.c
new revision: 1.2; previous revision: 1.1
done

Commit all the files in the project:

cvs commit -m "filled out C code"
cvs commit: Examining .
cvs commit: Examining a-subdir
cvs commit: Examining a-subdir/subsubdir
cvs commit: Examining b-subdir
Checking in a-subdir/subsubdir/fish.c;
/usr/local/cvs/myproj/a-subdir/subsubdir/fish.c,v  <--  fish.c
new revision: 1.2; previous revision: 1.1
done
Checking in b-subdir/random.c;
/usr/local/cvs/myproj/b-subdir/random.c,v  <--  random.c
new revision: 1.2; previous revision: 1.1
done

One thing you may notice is that revision numbers have been incremented.

Finding Out What You (And Others) Did - update And diff

Updating is a way of bringing changes down from the repository into your working copy - that is, as a way of getting other people's changes. However, update is really a bit more complex; it compares the overall state of the working copy with the state of the project in the repository. Even if nothing in the repository has changed since checkout, something in the working copy may have, and update will show that, too. For example:

cvs update
cvs update: Updating .
M hello.c
cvs update: Updating a-subdir
cvs update: Updating a-subdir/subsubdir
cvs update: Updating b-subdir

The M next to hello.c means the file has been modified since it was last checked out, and the modifications have not yet been committed to the repository.

However, if you want a more detailed look at the changes, you can get a full report in diff format. The diff command compares the possibly modified files in the working copy to their counterparts in the repository and displays any differences.

cvs diff

Extended information about basic use of diff. Examples with some options click here

Detecting And Resolving Conflicts

Detecting a conflict is easy enough. When you run update, CVS tells you, in no uncertain terms, that there's a conflict.

In some point we should have the status of our files in a similar situation to this example:

the status of our copy of hello.c is

cvs status hello.c
===================================================================
File: hello.c           Status: Needs Merge

   Working revision:    1.2     Mon Apr 19 02:17:07 1999
   Repository revision: 1.3     /usr/local/cvs/myproj/hello.c,v
   Sticky Tag:          (none)
   Sticky Date:         (none)
   Sticky Options:      (none)
meaning that there are changes both in the repository and the working copy, and these changes need to be merged.When we do the update, we see this:

cvs update hello.c
RCS file: /usr/local/cvs/myproj/hello.c,v
retrieving revision 1.2
retrieving revision 1.3
Merging differences between 1.2 and 1.3 into hello.c
rcsmerge: warning: conflicts during merge
cvs update: conflicts found in hello.c
C hello.c

The last line of output is the giveaway. The C in the left margin next to the filename indicates that changes have been merged, but that they conflict. The contents of the file now shows both changes. Conflicts are always shown delimited by conflict markers, in the following format:

<<<<<<< (filename)
  the uncommitted changes in the working copy
  blah blah blah
=======
  the new changes that came from the repository
  blah blah blah
  and so on
>>>>>>> (latest revision number in the repository)

Finding Out Who Did What (Browsing Log Messages)

By now, the project has undergone several changes. If you're trying to get an overview of what has happened so far, you don't necessarily want to examine every diff in detail. Browsing the log messages would be ideal, and you can accomplish this with the log command:

cvs log

The log output tends to be a bit verbose. Let's look at the log messages for just one file:

floss$ cvs log hello.c
RCS file: /usr/local/cvs/myproj/hello.c,v
Working file: hello.c
head: 1.4
branch:
locks: strict
access list:
symbolic names:
        start: 1.1.1.1
        jrandom: 1.1.1
keyword substitution: kv
total revisions: 5;     selected revisions: 5
description:
--------------
revision 1.4
date: 1999/04/20 04:14:37;  author: jrandom;  state: Exp;  lines: +1 -1
adjusted middle line
--------------
revision 1.3
date: 1999/04/20 02:30:05;  author: qsmith;  state: Exp;  lines: +1 -0
added new middle line
--------------
revision 1.2
date: 1999/04/19 06:35:15;  author: jrandom;  state: Exp;  lines: +1 -0
print goodbye too
--------------
revision 1.1
date: 1999/04/18 18:18:22;  author: jrandom;  state: Exp;
branches:  1.1.1;
Initial revision
--------------
revision 1.1.1.1
date: 1999/04/18 18:18:22;  author: jrandom;  state: Exp;  lines: +0 -0
initial import into CVS
========================================================================

When many files are sent in the same commit, they all share the same log message; a fact that can be useful in tracing changes.

When you run cvs log on them, you'll see the shared message:

cvs log a-subdir/subsubdir/fish.c b-subdir/random.c
RCS file: /usr/local/cvs/myproj/a-subdir/subsubdir/fish.c,v
Working file: a-subdir/subsubdir/fish.c
head: 1.2
branch:
locks: strict
access list:
symbolic names:
        start: 1.1.1.1
        jrandom: 1.1.1
keyword substitution: kv
total revisions: 3;     selected revisions: 3
description:
--------------
revision 1.2
date: 1999/04/19 06:35:27;  author: jrandom;  state: Exp;  lines: +8 -1
filled out C code
--------------
revision 1.1
date: 1999/04/18 18:18:22;  author: jrandom;  state: Exp;
branches:  1.1.1;
Initial revision
--------------
revision 1.1.1.1
date: 1999/04/18 18:18:22;  author: jrandom;  state: Exp;  lines: +0 -0
initial import into CVS
=========================================================================
RCS file: /usr/local/cvs/myproj/b-subdir/random.c,v
Working file: b-subdir/random.c
head: 1.2
branch:
locks: strict
access list:
symbolic names:
        start: 1.1.1.1
        jrandom: 1.1.1
keyword substitution: kv
total revisions: 3;     selected revisions: 3
description:
--------------
revision 1.2
date: 1999/04/19 06:35:27;  author: jrandom;  state: Exp;  lines: +8 -1
filled out C code
--------------
revision 1.1
date: 1999/04/18 18:18:22;  author: jrandom;  state: Exp;
branches:  1.1.1;
Initial revision
--------------
revision 1.1.1.1
date: 1999/04/18 18:18:22;  author: jrandom;  state: Exp;  lines: +0 -0
initial import into CVS
=========================================================================

Examining And Reverting Changes

You can compare two past revisions using the -r command option to specify both of them:

cvs diff -c -r 1.3 -r 1.4 hello.c

How can you retrieve the contents of an older revision and put them into a new one?

Use the -j (for "join") flag to the update command. This flag is like -r in that it takes a revision number, and you can use up to two -j's at once. CVS calculates the difference between the two named revisions and applies that difference as a patch to the file in question (so the order in which you give the revisions is important).

cvs update -j 1.4 -j 1.3 hello.c
RCS file: /usr/local/cvs/myproj/hello.c,v
retrieving revision 1.4
retrieving revision 1.3
Merging differences between 1.4 and 1.3 into hello.c
paste$ cvs update
cvs update: Updating .
M hello.c
cvs update: Updating a-subdir
cvs update: Updating a-subdir/subsubdir
cvs update: Updating b-subdir
paste$ cvs ci -m "reverted to 1.3 code" hello.c
Checking in hello.c;
/usr/local/cvs/myproj/hello.c,v  <--  hello.c
new revision: 1.5; previous revision: 1.4
done

Later in the manual will be shown how to do to revert multiple files at once

Adding Files

Adding a file is a two-step process: First you run the add command on it, then commit. The file won't actually appear in the repository until commit is run:

cvs add newfile.c
cvs add: scheduling file 'newfile.c' for addition
cvs add: use 'cvs commit' to add this file permanently
cvs ci -m "added newfile.c" newfile.c
RCS file: /usr/local/cvs/myproj/newfile.c,v
done
Checking in newfile.c;
/usr/local/cvs/myproj/newfile.c,v  <-  newfile.c
initial revision: 1.1
done

Adding Directories

Unlike adding a file, adding a new directory is done in one step; there's no need to do a commit afterwards:

mkdir c-subdir
cvs add c-subdir
Directory /usr/local/cvs/myproj/c-subdir added to the repository

Now you can add files (or new directories) inside it, as with any other working copy directory.

CVS And Binary Files

CVS doesn't handle binary files very well.

When you add a binary file, you have to tell CVS to turn off both keyword expansion and line-ending conversion. To do so, use -kb:

cvs add -kb filename
cvs ci -m "added blah" filename
  (etc)

Removing Files

Removing a file is similar to adding one, except there's an extra step: You have to remove the file from the working copy first:

floss$ rm newfile.c
cvs remove newfile.c
cvs remove: scheduling 'newfile.c' for removal
cvs remove: use 'cvs commit' to remove this file permanently
cvs ci -m "removed newfile.c" newfile.c
Removing newfile.c;
/usr/local/cvs/myproj/newfile.c,v  <-  newfile.c
new revision: delete; previous revision: 1.1
done

Notice how, in the second and third commands, we name newfile.c explicitly even though it doesn't exist in the working copy anymore. Of course, in the commit, you don't absolutely need to name the file, as long as you don't mind the commit encompassing any other modifications that may have taken place in the working copy.

Removing Directories

As I said before, CVS doesn't really keep directories under version control. Instead, as a kind of cheap substitute, it offers certain odd behaviors that in most cases do the "right thing". One of these odd behaviors is that empty directories can be treated specially. If you want to remove a directory from a project, you first remove all the files in it

cd dir
rm file1 file2 file3
cvs remove file1 file2 file3
  (output omitted)
cvs ci -m "removed all files" file1 file2 file3
  (output omitted)

and then run update in the directory above it with the -P flag:

cd ..
cvs update -P
  (output omitted)

The -P option tells update to "prune" any empty directories - that is, to remove them from the working copy. Once that's done, the directory can be said to have been removed; all of its files are gone, and the directory itself is gone (from the working copy, at least, although there is actually still an empty directory in the repository).

Renaming Files And Directories

Renaming a file is equivalent to creating it under the new name and removing it under the old.

mv oldname newname
cvs remove oldname
  (output omitted)
cvs add newname
  (output omitted)
cvs ci -m "renamed oldname to newname" oldname newname
  (output omitted)

For files, that's all there is to it. Renaming directories is not done very differently: create the new directory, cvs add it, move all the files from the old directory to the new one, cvs remove them from the old directory, cvs add them in the new one, cvs commit so everything takes effect, and then do cvs update -P to make the now-empty directory disappear from the working copy. That is to say:

floss$ mkdir newdir
cvs add newdir
mv olddir/* newdir
mv: newdir/CVS: cannot overwrite directory
cd olddir
cvs rm foo.c bar.txt
cd ../newdir
cvs add foo.c bar.txt
cd ..
cvs commit -m "moved foo.c and bar.txt from olddir to newdir"
cvs updComing soon.......ate -P

Note: the warning message after the third command. It's telling you that it can't copy olddir's CVS/ subdirectory into newdir because newdir already has a directory of that name. This is fine, because you want olddir to keep its CVS/ subdirectory anyway.

Getting Snapshots (Dates And Tagging)

CVS provides a way to retrieve previous revisions of the files in a project en masse. In fact, it provides two ways: by date, which selects the revisions based on the time that they were committed, and by tag, which retrieves a previously marked "snapshot" of the project.

Which method you use depends on the situation. The date-based retrievals are done by passing update the -D flag, which is similar to -r but takes dates instead of revision numbers:

cvs -q update -D "1999-04-19"
U hello.c
U a-subdir/subsubdir/fish.c
U b-subdir/random.c

With the -D option, update retrieves the highest revision of each file as of the given date, and it will revert the files in the working copy to prior revisions if necessary.

When you give the date, you can, and often should, include the time.

Coming soon.......cvs -q update -D "1999-04-19 23:59:59"
U hello.c
U a-subdir/subsubdir/fish.c
U b-subdir/random.c

You can also specify the GMT zone in the command:

cvs -q update -D "1999-04-19 23:59:59 GMT"

Acceptable Date Formats

CVS accepts a wide range of syntaxes to specify dates.

You will probably never need all of the formats available, but here are some more examples to give you an idea of what CVS accepts:

cvs update -D "19 Apr 1999"
cvs update -D "19 Apr 1999 20:05"
cvs update -D "19/04/1999"
cvs update -D "3 days ago"
cvs update -D "5 years ago"
cvs update -D "19 Apr 1999 23:59:59 GMT"
cvs update -D "19 Apr"

The double quotes around the dates are there to ensure that the Unix shell treats the date as one argument even if it contains spaces. The quotes will do no harm if the date doesn't contain spaces, so it's probably best to always use them.

Marking A Moment In Time (Tags)

Retrieving by date is useful when the mere passage of time is your main concern. But more often what you really want to do is retrieve the project as it was at the time of a specific event - perhaps a public release, a known stable point in the software's development, or the addition or removal of some major feature.

Setting a tag is as simple as this:

cvs -q tag Release-1999_05_01
T README.txt
T hello.c
T a-subdir/whatever.c
T a-subdir/subsubdir/fish.c
T b-subdir/random.

That command associates the symbolic name "Release-1999_05_01" with the snapshot represented by this working copy. Defined formally, snapshot means a set of files and associated revision numbers from the project. Those revision numbers do not have to be the same from file to file and, in fact, usually aren't.

The rules for naming tags are that it must start with a letter and contain letters, digits, hyphens ("-"), and underscores ("_"). No spaces, periods, colons, commas, or any other symbols may be used.

To retrieve a snapshot by tag name, the tag name is used just like a revision number. There are two ways to retrieve snapshots: You can check out a new working copy with a certain tag, or you can switch an existing working copy over to a tag. Both result in a working copy whose files are at the revisions specified by the tag.

Most of the time, what you're trying to do is take a look at the project as it was at the time of the snapshot. You may not necessarily want to do this in your main working copy, where you presumably have uncommitted changes and other useful states built up, so let's assume you just want to check out a separate working copy with the tag. Here's how (but make sure to invoke this somewhere other than in your existing working copy or its parent directory!):

cvs checkout -r Release-1999_05_01 myproj
cvs checkout: Updating myproj
U myproj/README.txt
U myproj/hello.c
cvs checkout: Updating myproj/a-subdir
U myproj/a-subdir/whatever.c
cvs checkout: Updating myproj/a-subdir/subsubdir
U myproj/a-subdir/subsubdir/fish.c
cvs checkout: Updating myproj/b-subdir
U myproj/b-subdir/random.c
cvs checkout: Updating myproj/c-subdir

We've seen the -r option before in the update command, where it preceded a revision number.

Switching an existing working directory over to the tagged revisions-is also done by updating:

cvs update -r Release-1999_05_01
cvs update: Updating .
cvs update: Updating a-subdir
cvs update: Updating a-subdir/subsubdir
cvs update: Updating b-subdir
cvs update: Updating c-subdir


-- CarlosArrastia - 30 Jan 2004

Information summarized from the following website:
http://cvsbook.red-bean.com/cvsbook.html