Setting Up CVSNT and WinCVS
This document describes the installation and configuration of CVS client and server applications on the Windows® XP platform. Before you embark upon following these instructions, you should be aware that you are likely to have more difficulty running a CVS server on a Windows platform, compared with a *nix platform. CVS clients running on Windows platforms seem to do fairly well, though.
CVSNT (server) version 2.5.03.2260 and
WinCVS (client) 18.104.22.168 (Build 4) were used. In addition,
WinMerge 2.4.10 was used for merge and diff tool functions.
New clients (users) require the installation of CVSNT and WinCVS on their local machine.
- Install CVSNT first. The installer file can be found here:
- Install WinCVS second. The installer file can be found here:
- Finally, install WinMerge as the external tool for handling graphical differences. The installer file can be found here:
- Alternatively, WinDiff.exe can be used as the external difference tool. It may already be installed under the Visual Studio directory tree (e.g. C:\Program Files\Microsoft Visual Studio\COMMON\Tools or C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin). WinDiff is more bare-bones than WinMerge, but is generally sufficient for simply viewing differences between files.
Setting up CVSNT Server
If someone has already setup a CVS server, you can skip to the next section. Otherwise, you will need to make some changes to allow the CVS server to use Windows for authentication. Go to the $CVSROOT (or %CVSROOT% for Windows-types) directory on the server. There will be a file named config. You must edit that file to enable "SystemAuth". To match the settings I will later describe for the client, you should also enable/require encryption on the CVS server. (your requirements may differ, but generally encryption is recommended and will not overly restrict performance for small to medium sized projects). To enable encryption select Start Menu -> Programs -> CVSNT -> CVSNT Control Panel. Choose Server Settings -> Encryption -> Require Encryption.
Adding User Account on Server
For a Windows XP only environment (both client and server), Windows NT authentication should be used for authenticating users to the CVS server. Existing Windows logon credentials can be used to gain access, but the server needs to be configured to recognize which users can be authenticated in this manner.
- On the CVS server, edit the $CVSROOT/passwd file (e.g. C:\home\cvsroot\CVSROOT\passwd).
- Enter a line for the new user. The username will be the same username used for normal Windows logons. The Windows domain is also needed. This file does not actually need the exact password, or even hashed password, to properly setup CVS. You can merely enter garbage for the hashed password field. The easiest way to go is to simply copy an existing line and change the username. For example:
- Save the passwd file.
- You should probably restart the CVS server. Ask the other users first, to avoid conflicts if they are in the middle of checkins, etc. To restart the server, login to the server machine, and select Start Menu -> CVSNT -> CVSNT Control Panel. Click the Stop button for the CVSNT Service, and the CVSNT Lock Service. Then, click the Start button for each service to restart it.
- Set Windows environment variables to establish the default CVS server and communication protocol. To use Windows authentication, you need the "sspi" protocol. Select Start Menu -> Settings -> Control Panel -> System -> Advanced. Click on Environment Variables. Add a New user variable. Call it CVSROOT (all caps). The value of the environment variable should be:
:sspi:DOMAIN\firstname.lastname@example.org:/home/cvsroot (Note the leading colon!!)
You may need to logout and log back in for the environment variable to take effect.
- Set WinCVS preferences to appropriate values. Open the WinCVS GUI and select Admin -> Preferences. On the various tabs, you should have the following values:
- Setup default .cvsignore file. This file specifies some default file types that should not be "tracked" by CVS. You can copy the .cvsignore file here, and place it in the same directory specified in WinCVS (CVS) preferences as the HOME directory (a network drive in the above screenshot).
Accessing CVSNT from UNIX Clients
The CVSNT server can be accessed equally from windows and *NIX clients. Most *NIX systems have the cvs command line client already installed somewhere on your path. To securely use the cvs client, you will need to setup SSH public key authentication on the client (*NIX) and server (windows) machine. Assuming the server already has a SSH daemon installed (e.g. the Cygwin SSH daemon), you will need to create a client-side key and store it on the server. This key will then be used automatically by cvs to tunnel all communications from client to server thru SSH.
- First, login to your *NIX machine.
- If there is not a
.ssh directory immediately under your home directory, create it (mkdir .ssh).
- This directory will contain a key that will authenticate you to the server, so you should not let anyone else read this directory. Change its permissions with:
chmod 700 .ssh
- cd to the .ssh directory. You will now need to create a private/public key pair.
[username@host]/home/username/.ssh> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/username/.ssh/id_rsa.
Your public key has been saved in /home/username/.ssh/id_rsa.pub.
The key fingerprint is:
You should also make sure that the id_rsa file has permissions -rw-------, and id_rsa.pub has permissions -rw-r-----.
- Now, you need to configure the server to recognize this keypair. To do that, you must copy the public key text from id_rsa.pub into a special location on the server. First, of all, you need to make sure that the server has a Cygwin (*NIX emulation) account for your user. Open up a Cygwin shell on the server and do the following:
$ mkpasswd -d DOMAIN -u username -p /home/ >> /etc/passwd
You will see a line like this added to /etc/passwd (which in a Windows file explorer will be under something like c:\Cygwin\etc\passwd):
username:unused_by_nt/2000/xp:376263:10993:Doe, John Q,U-DOMAIN\username,S-1-5-21-2022655429-1303542900-1413331333-361263:/home/username:/bin/bash
I also recommend editing the passwd file (using Wordpad via a Windows explorer), and change the default shell from /bin/bash to /usr/bin/tcsh.
- Now, use Windows to create a home directory (e.g. C:\Cygwin\home\username).
- Then, use the Cygwin shell to again create a .ssh directory under /home/username. Change permissions as described above.
- cd to .ssh. Now you must put the public key you created into a file of recognized keys, which must be called "authorized_keys" (in the .ssh directory). It
will look something like this:
Make sure this is all on one line!! .. no line breaks should appear in the public key (or spaces!).
- Now, from the client *NIX side, you should be able to login using the public key you've setup simply with
ssh username@servername, where in this case, servername is the fully-qualified domain name of the CVS server (Cygwin) machine.
- Finally, you need to configure the *NIX CVS client to use your ssh connection. Set two environment variables:
setenv CVSROOT :ext:username@servername:/cygdrive/c/home/cvsroot
setenv CVS_RSH /usr/bin/ssh
It's probably a good idea to put these two lines in your ~/.cshrc file, so you don't have to set them after every login.
- Then, if you enter the directory you'll be using as your sandbox, you can checkout files with "cvs checkout [modulename]". CVS uses the environment variables to connect to the proper server
with ssh, and use the keypair you setup to perform encryption and authentication.
Using Your CVS Sandbox
- Establish a local location for your CVS sandbox (aka "snapshot view"). For performance reasons, a local drive is preferred. However, if your local drive is not regularly backed up, there is a data redundancy issue with keeping your work on a local drive. If you are in the habit of frequently checking in your changes (e.g. nightly), then you are probably ok. If you have the bad habit of keeping work checked out for a long time between commits, then you may be taking a risk of losing work. You can coordinate with your sysadmin about this, or perhaps write your own backup script to copy your sandbox nightly to a backed-up network location (using Windows Scheduled Tasks, for example). Once changes have been committed, they are on the server, which may (or may not :( ) be backed up regularly.
- Test checking out the required code modules, populating your local sandbox. You need to know the name of the desired code module in CVS to checkout files, which is the relative pathname of the module in the CVS repository (relative to the CVSROOT directory). Enter it into the first text field on the WinCVS checkout dialog.
Edit and commit changes. No special action is required to checkout individual files within a module, as long as you do not need to make "reserved" edits, which require obtaining a lock on the file in question. In general, using reserved edits is discouraged. Prefer verbal communication with other developers to coordinate work on common files.
To modify a source file, simply start editing it. Once changes are saved, the file will be highlighted red in your WinCVS explorer window. You can filter the display in WinCVS to show all files, or only those files which have been modified since your last module checkout. To commit (aka "checkin") changes, simply right-click on one of the red-highlighted files within WinCVS and select "commit". You can (and should!) then enter a short description of your changes and submit the request to commit. If someone else has modified and committed the file since you last checked that file out, the attempt to commit will fail (up-to-date check failure). You will then need to update that file first. If there are no conflicts, then you can retry the commit process. If there are conflicts, you will see a red message saying so in the WinCVS console output frame
rcsmerge: warning: conflicts during merge
cvs update: conflicts found in Something.cpp
You should get in the habit of viewing the WinCVS console for errors whenever issuing commands.
Text vs. Binary files. For all text files, CVS can keep track of versions by saving differences. This is highly efficient, and also allows you to see differences between different versions. For binary files, there is no good way to view differences, and file versions are stored by CVS as full binary blobs (less efficient). Therefore, when you add new files to the CVS repository, you should take care to specify whether or not you are adding a text or binary file type. CVS can try to figure this out on its own, but if you're only adding a few files at a time, it's better to tell it explicitly whether the file is text or binary. You create a new file in the normal way. When you are ready to put it under CVS control, make sure that it resides in a CVS-controlled directory. If the directory itself is new (but underneath a CVS-controlled directory), then you can highlight the directory in WinCVS and click the Add button on the toolbar. Then, you can highlight the new file, and click either the normal Add, or Add Binary button to "schedule the file for addition". To finalize the process, you select the file, which should be highlighted red by WinCVS, and do a "commit" ... just as if you had changed an existing file.
Tagging (aka "labeling") files to identify versions. To establish a named version, you apply a "tag" to files in your sandbox. Whatever is present in your sandbox will be the version tagged. You can select directories, and tag everything under that directory tree. To do this, select the top level directory (or single file, if that's all you want to tag) and click the Tag button on the toolbar. You must specify the tag name, which needs to conform to the usual code naming conventions (must contain standard numbers and letters, and start with a letter ... not a number!) Suggested pattern would be something like:
for version 1.2.0
Viewing differences. To view differences between the version of a file in your sandbox, and the version you originally checked out (which is not necessarily the newest version!) .. simply highlight the file in your WinCVS explorer. Right-click and select Diff, or click the Diff button on the toolbar. WinCVS will spawn your external diff viewer application, assuming you specified one in your Preferences. If you want to see differences between any two arbitrary versions, you should select the file in WinCVS and click the version tree button on the toolbar. On the version tree, you can then use Ctrl-click to select more than one version on the tree. Then, right-click and choose Diff to see the differences in your external viewer.
Merging files when there are conflicts. If you update a file in your sandbox, and you have already modified parts of the file that were also changed by someone else in an "interlaced" submission, then there will be a conflict. CVS automatically merges trivial conflicts on its own. If parallel changes affect the same lines, however, it leaves both versions in the merged file, tells you about the conflict in the console frame, and identifies the section as follows:
m_zero = 0;
m_one = 1;
m_two = 2;
m_number = 0;
m_hasData = false;
for (int it = 0; it < MAX_NUM; ++it)
It is then your responsibility to edit the file and remove whichever section you think should not be there, and also remove the
lines that CVS inserted.
Updating your sandbox manually. The files in your sandbox only change when you changed them, or when you decide to let CVS update them. This gives you isolation from other developers' changes. When you do want to get newer versions of other peoples' work, you can choose to udpate your entire sandbox, individual files, or anywhere in between. Select those files, or directories, to update in WinCVS, right-click, and choose Update. If you do not select "Get the clean copy", you are asking CVS to merge differences between the newer version, and what's in your sandbox. Usually, no merging is necessary. However, sometimes, you want to get rid of the changes you've made in your sandbox entirely (revert to the version in the CVS server's repository). In that case, select "Get the clean copy" when doing a CVS Update. Your local file will be moved to a .#* file in your sandbox, in case you later decide that you didn't really want to blow away all your changes. Another thing to be concerned with is that another developer may add a whole new directory to CVS. When that happens, you need to do more than the basic Update to get the new directory tree. On the WinCVS Update dialog, check "Create missing directories that exist in the repository". This should virtually always be your preferred setting.
There is a problem that WinCVS has if you have Cygwin installed on your machine. See here for details. You basically should rename or delete tcl84.dll to avoid conflicts.
If accessing the CVSNT server from a *nix client, and using a Cygwin sshd on the server to provide a secure tunnel, you may see this error message in
cvs server: syntax error in /cygdrive/c/home/cvsroot/CVSROOT/config: line '' is missing '='
This is a problem concerning end of line (newline) differences between Windows and *nix. You have probably created, and maybe edited the config file
with a Windows-type editor, which then causes problems for the Cygwin (*nix) CVS client. I don't believe this to be a serious problem, but I found that
if you remove the Windows newlines from the 'config' file, you will stop getting that error message, and things will still work fine on the Windows side.
I recommend using the
dos2unix command in a server Cygwin shell to strip the Windows newlines out.
Also, sometimes I see this error message in my WinCVS output window:
cvs update: warning: unrecognized response
`FATAL ERROR: Server unexpectedly closed network connection' from cvs server
cvs [update aborted]: end of file from server (consult above messages if any)
When this occurs, I generally log onto the CVS server machine, and from a command line do:
net stop sshd
net start sshd
And that fixes the apparent tunnel corruption.