The command to check out a project is exactly what you think it is:
floss$ cvs checkout 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 floss$ ls myproj/ was_myproj/ floss$ cd myproj floss$ ls CVS/ README.txt a-subdir/ b-subdir/ hello.c floss$
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:
floss$ ls a-subdir CVS/ subsubdir/ whatever.c floss$ ls a-subdir/subsubdir/ CVS/ fish.c floss$ ls b-subdir CVS/ random.c
The fact that CVS keeps its revision information in subdirectories named CVS means that your project can never contain subdirectories of its own named CVS. In practice, I've never heard of this being a problem.
Before editing any files, let's take a peek inside the black box:
floss$ cd CVS floss$ ls Entries Repository Root floss$ cat Root /usr/local/cvs floss$ cat Repository myproj floss$
Nothing too mysterious there. The Root file points to repository, and the Repository file points to a project inside the repository. If that's a little confusing, let me explain.
There is a longstanding confusion about terminology in CVS. The word "repository" is used to refer to two different things. Sometimes, it means the root directory of a repository (for example, /usr/local/cvs), which can contain many projects; this is what the Root file refers to. But other times, it means one particular project-specific subdirectory within a repository root (for example, /usr/local/cvs/myproj, /usr/local/cvs/yourproj, or /usr/local/cvs/fish). The Repository file inside a CVS subdirectory takes the latter meaning.
In this book, "repository" generally means Root (that is, the top-level repository), although it may occasionally be used to mean a project-specific subdirectory. If the intended sense can't be figured out from the context, there will be clarifying text. Note that the Repository file may sometimes contain an absolute path to the project name instead of a relative path. This can make it slightly redundant with the Root file:
floss$ cd CVS floss$ cat Root :pserver:email@example.com:/usr/local/cvs floss$ cat Repository /usr/local/cvs/myproj floss$
The Entries file stores information about the individual files in the project. Each line deals with one file, and there are only lines for files or subdirectories in the immediate parent directory. Here's the top-level CVS/Entries file in myproj:
floss$ cat Entries /README.txt/22.214.171.124/Sun Apr 18 18:18:22 1999// /hello.c/126.96.36.199/Sun Apr 18 18:18:22 1999// D/a-subdir//// D/b-subdir////
The format of each line is
/filename/revision number/last modification date//
and the directory lines are prefixed with "D". (CVS doesn't really keep a change history for directories, so the fields for revision number and datestamp are empty.)
The datestamps record the date and time of the last update (in Universal Time, not local time) of the files in the working copy. That way, CVS can easily tell whether a file has been modified since the last checkout, update, or commit. If the file system timestamp differs from the timestamp in the CVS/Entries file, CVS knows (without even having to consult the repository) that the file was probably modified.
If you take a look at the CVS/* files in one of the subdirectories
floss$ cd a-subdir/CVS floss$ cat Root /usr/local/cvs floss$ cat Repository myproj/a-subdir floss$ cat Entries /whatever.c/188.8.131.52/Sun Apr 18 18:18:22 1999// D/subsubdir//// floss$
you can see that the root repository has not changed, but the Repository file spells out the location of this subdirectory of the project, and the Entries file contains different lines.
Immediately after import, the revision number of every file in the project is shown as 184.108.40.206. This initial revision number is a bit of a special case, so we won't examine it in detail just yet; we'll take a closer look at revision numbers after we've committed some changes.