CVS Tutorial - Answers

You have an account (jdoe) on cvs.mydomain.com. The project you are currently working on has a repository in /projects/myproj/cvsroot. The repository has two modules: src and doc.


How can you checkout your own working copy of all available modules to ~/myproj? Please note that the CVS server does allow only SSH connections.


# export CVS_RSH=ssh
# cvs -d jdoe@cvs.mydomain.com:/projects/myproj/cvsroot co -P src doc

You haven't worked on the code for a while. How can you get the latest sources into your previously checked-out working copy?


# cd src
# cvs update -dP

You have changed one of the original source files (src/main.c). How can you see the changes before commiting your version?


# cd src
# cvs diff -u main.c

You know another project member has modifed the same file as you. How can you see his changes without updating your working copy?


# cvs log filename
[The other member created revision 1.42 while your code is still based on 1.41]
# cvs diff -u -r 1.41 -r 1.42 filename

You update your working copy before checking in your changes and you get a warning about conflicts. How can you find the conflicts in this file?


Open the file with a text editor and search for <<<.

You have finally managed to resolve all conflicts and you want to commit your changes. Give two ways to do it: 1) type the commit message in emacs and 2) give a short commit message on the command line.


# export EDITOR=emacs
# cvs ci filename

# cvs ci -m "Some message" filename

How can you see what tags are used for a file?


# cvs status -v filename

You have committed your changes and you want to put a symbolic tag on the sources before adding a new feature. How do you tag a single file? How do you tag all files in the current directory? How do you recursively tag all files in the current directory and all subdirectories?


# cvs tag MYTAG file
# cvs tag -l MYTAG
# cvs tag MYTAG

You have finished with your experimental stuff. How can you see what has been changed since the previously defined tag?


# cvs diff -u -r MYTAG

At the same time as you made the (still uncommitted) weird changes someone else modified somethig. How can you see what was changed in the HEAD branch since your tag?


# cvs diff -u -r MYTAG -r HEAD

In your project you need a slightly modified KPhone. How can you import the KPhone 4.1 sources into the KPHONE branch so that they appear in src/kphone?


# cd /tmp
# tar xfz kphone-4.1.tar.gz
# cd kphone-4.1
# cvs -d jdoe@cvs.mydomain.com:/projects/myproj/cvsroot import -ko \
  -m "Imported KPhone 4.1" src/kphone KPHONE KPHONE-4_1

You would like to create a backup of the repository before importing the new KPhone. How can you do it?


# ssh jdoe@cvs.mydomain.com
# cd /projects/myproj
# tar czf 20051104.tgz cvsroot

After some time a new KPhone is released (version 4.2). How can you import it into the same KPHONE branch and merge the changes made between 4.1 and 4.2 into the HEAD branch?


# cd /tmp
# tar xfz kphone-4.2.tar.gz
# cd kphone-4.2
# cvs -d jdoe@cvs.mydomain.com:/projects/myproj/cvsroot import -ko \
  -m "Imported KPhone 4.2" src/kphone KPHONE KPHONE-4_2

# cd ~/src/kphone
# cvs update -d -kk -jKPHONE-4_1 -jKPHONE-4_2
# cvs ci -m "Merged KPhone 4.2 to HEAD"

Bonus question: what does the cvs -H admin -m 1.42:"New message" filename command do?

This was a trick question; it displays the usage information of the "cvs admin" command. Without the -H option it would have changed revision 1.42's commit message.


# cvs -H admin -m 1.42:"New message" filename
Usage: cvs admin [options] files...
        -a users   Append (comma-separated) user names to access list.
        -A file    Append another file's access list.
        -b[rev]    Set default branch (highest branch on trunk if omitted).
        -c string  Set comment leader.
        -e[users]  Remove (comma-separated) user names from access list
                   (all names if omitted).
        -I         Run interactively.
        -k subst   Set keyword substitution mode:
           kv   (Default) Substitute keyword and value.
           kvl  Substitute keyword, value, and locker (if any).
           k    Substitute keyword only.
           o    Preserve original string.
           b    Like o, but mark file as binary.
           v    Substitute value only.
        -l[rev]    Lock revision (latest revision on branch,
                   latest revision on trunk if omitted).
        -L         Set strict locking.
        -m rev:msg  Replace revision's log message.
        -n tag[:[rev]]  Tag branch or revision.  If :rev is omitted,
                        delete the tag; if rev is omitted, tag the latest
                        revision on the default branch.
        -N tag[:[rev]]  Same as -n except override existing tag.
        -o range   Delete (outdate) specified range of revisions:
           rev1:rev2   Between rev1 and rev2, including rev1 and rev2.
           rev1::rev2  Between rev1 and rev2, excluding rev1 and rev2.
           rev:        rev and following revisions on the same branch.
           rev::       After rev on the same branch.
           :rev        rev and previous revisions on the same branch.
           ::rev       Before rev on the same branch.
           rev         Just rev.
        -q         Run quietly.
        -s state[:rev]  Set revision state (latest revision on branch,
                        latest revision on trunk if omitted).
        -t[file]   Get descriptive text from file (stdin if omitted).
        -t-string  Set descriptive text.
        -u[rev]    Unlock the revision (latest revision on branch,
                   latest revision on trunk if omitted).
        -U         Unset strict locking.
(Specify the --help global option for a list of other help options)