TortoiseCVS Daily Use Guide

Or: How to finally enjoy version control

Adapted from the excellent WinCVS Daily Use Guide by Sverre Huseby.


Table 'o Stuff

  1. Sandboxes
  2. Getting a Module from CVS
  3. Icon Overlay Colours
  4. Getting Other People's Changes from CVS
  5. Sending Your Changes to CVS
  6. Resolving Conflicts
  7. Viewing Changes
  8. Adding Files and Directories
  9. Removing Files and Directories
  10. Moving or Renaming Files and Directories
  11. Canceling changes
  12. Tagging Files with a Label
  13. Starting a New Module
  14. Branching
  15. Selecting a Branch to Work on
  16. Merging from a Branch
  17. Going Back to the Main Line of Development
  18. Appendix A: Terminology
  19. Appendix B: How CVS Differs from Microsoft Visual Source Safe

Sandboxes

CVS has a different way of working from other version control systems. Developers can edit the same files concurrently. First you checkout a version of the source from the repository. Then you simply edit the files that you want to change, and make new files or delete them. When you're done you commit the files to the repository.

If someone else has changed the same file while you were working on it, then the commit will fail. You then update all your source code files from the repository. This will automatically merge the other developers changes into your copy of the file.

Sometimes it can't do this automatically, for example if you both changed the same line of code. This is called a conflict. Conflicts happen much less often than you might expect. CVS puts both versions of the conflicting code in the file, with markings separating them. Then you manually edit the file to resolve the conflict.

Now you can commit again, and this time it will work.

This method of working has lots of advantages. Each developer lives in a sandbox. Changes that another developer makes are isolated from you until you want to check in your changes. It stops bottlenecks where people can't do things because someone else has the file checked out. Any developer can work on files without direct access to the server, they only need to connect to update or commit.

[ CVS Doc: "Overview" ]

Getting a Module from CVS

To obtain a module from the CVS server for the first time, is known as a checkout. Checking a module out from the repository gives you a local copy of the directory hierarchy that makes up the module.

If you've already checked out your module using WinCVS or another CVS client you can skip this section and just start working on it.

To perform a checkout, Right click on the directory where you'd like the module placed, and pick "CVS Checkout..." from the pop-up menu. The checkout dialog should appear with the following fields:

Protocol
Which protocol to use when talking to the server.
Server
Name of the machine holding the repository.
Repository Directory
This is the location of the repository on the server.
User name
The username of your account on the repository server.
Module
The name of the module you want to check out. The module name is case sensitive.
CVSROOT
A read-only field which displays the full connection string, composed from the above fields (other CVS clients require you to supply the connection string in this format).

You'll need to know this information in advance. Most projects should have some documentation (often online) on how to connect and checkout their modules. Failing that, you'll just have to find someone in the know :-).

A directory named after the module will be created in the directory you checkout to, so you can keep all your checked out modules in the same directory if you'd like, even if they are for different projects.

[ CVS Doc: "checkout -- Check out sources for editing" ]

Icon Overlay Colours

You will see some files and folders now have an icon overlay.

Getting Other People's Changes from CVS

Occasionally you may want changes done by others to get incorporated in your local working copy. The process of getting changes from the server to your local copy is known as updating. Updating may be done on single files, a set of selected files, or recursively on entire directory hierarchies. To update, highlight the files and/or directories you want, right click and select "CVS Update". A window will pop up displaying the progress of the update as it runs.

Changes done by others will be merged into your files, keeping any changes you may have done to the same files. The repository is not affected by an updating.

If you receive reports of conflicts during the update, please read the "resolving conflicts" section.

The update output section in the CVS manual describes the cryptic codes which appear at the start of each progress line.

[ CVS Doc: "Bringing a file up to date" ]
[ CVS Doc: "update -- Bring work tree in sync with repository" ]

Sending Your Changes to CVS

Making local modifications available in the repository is known as committing the changes.

  1. Before committing, you should do an update to make sure there are no conflicts. See Getting Other People's Changes from CVS.
  2. Select the directory, file or files that you want to commit.
  3. Click the right mouse button on the selction, and choose the CVS Commit... menu item.
  4. In the commit dialog, enter a log message with a brief summary of what was changed.
  5. Files can be excluded from the commit by unchecking their tickboxes.
  6. Click OK on the dialog to go ahead with the commit operation.

Please note that committing changes will not automatically add new files that you have created to the repository. See Adding Files and Directories for a description of doing that.

[ CVS Doc: "commit -- Check files into the repository" ]

Resolving Conflicts

Once in a while, the CVS server will report a conflict when you update your files from the repository. A conflict occurs when two or more developers have changed the same few lines of a file. As CVS knows nothing of your project, it leaves resolving the conflicts to the developers. Whenever a conflict is reported, you should open the file in question, and search for lines starting with the string <<<<<<<. The conflicting area is marked like this:

<<<<<<< filename
    your changes
=======
    code merged from repository
>>>>>>> revision

You should decide what the code should look like, do the necessary changes, remove the CVS markup, and commit your modifications to the repository.

[ CVS Doc: "Conflicts example" ]

Adding Files and Directories

If you've made new files or directories you will notice that its icon appears with a question mark on it. To put such files or directorys under CVS control:

  1. Select the item(s) that you want to add.
  2. Choose CVS Add from the right-click menu to schedule the addition.

After an add operation on a file, the file icon appears as "changed". This is because additions are treated as local changes and are not applied to the repository until you commit them.

For directories, an extra menu item, CVS Add All Recursively, is available. This operation descends down the directory structure, performing an addition on everything, including subdirectories. Be careful with this, as you don't want to accidentally add superfluous crap into your repository (for example, intermediate compiler files like .o or .obj).

You don't need to worry about whether a file is binary or not, TortoiseCVS automatically detects this. See the FAQ entry for more information.

[ CVS Doc: "Adding, removing, and renaming files and directories" ]

Viewing Changes

To see the changes that have been made to a file, select the CVS Diff... menuitem.

The Web Log option launches your browser into ViewCVS or CVSWeb to view the history of a file. These programs let you browse the CVS repository, download old versions and display differences between them. I highly recommend that you persuade your server administrator to install ViewCVS - it supports the useful Annotate feature which tells you who last changed each line of code.

[ CVS Doc: "diff -- Show differences between revisions" ]
[ CVS Doc: "log -- Print out log information for files" ]

Removing Files and Directories

To remove files, you first schedule the files for removal, and then commit the change:

  1. Select the file or files that you want to remove.
  2. Click the right mouse button on the selction, and choose the CVS/Remove submenu item.
  3. The files are removed locally and scheduled for removal in the repository. You have to perform a commit to apply the changes to the repository.

The files will now be removed from the repository and from your working set.

Directories are automatically removed when all their contents have been removed.

[ CVS Doc: "Adding, removing, and renaming files and directories" ]

Moving or Renaming Files and Directories

Operation of moving or renaming files or directories is not available in CVS. This is one of CVS's shortcomings. To simulate moving or renaming, you have to combine remove and add operations. See Adding Files and Directories and Removing Files and Directories.

[ CVS Doc: "Moving and renaming files" ]

Canceling Changes

The easiest way to cancel the changes that you have made to a file is to delete the file on your hard disk. Then choose update on the directory, and you will get the latest version back again.

Tagging Files with a Label

At a given stage of development, giving one or more files a common label to refers to their revisions, is known as tagging those files. Tagging is typically used on entire modules, so that the current state of the module can be reconstructed in the future. This kind of tagging should always be done on project deliverables, and before starting major changes.

To tag one or more files or directories with a label, do the following:

  1. Select the directory, file or files that you want to tag.
  2. Click the right mouse button on the selction, and choose the CVS/Create Tag... menu item.
  3. Enter the label in the Tag input field. (See below for restrictions on tag names.)
  4. Press the OK button.

Note that the tag is immediately applied to the repository - no commit is required.

CVS is quite restrictive when it comes to what characters a tag may contain: A tag must start with a letter, and may contain letters, digits, "-" (dash) and "_" (underscore) only. In particular, this means no dots, and no spaces. If you want to include version numbers in a tag, replace the dots with dashes. Two tag names are reserved, as they have special meaning in CVS: "HEAD" refers to the most recent version available in the repository, while "BASE" is the revision you last checked out into the local directory.

[ CVS Doc: "Tags -- Symbolic revisions" ]

Starting a New Module

To create a new CVS module:

  1. Organise a directory with the files you want to put under CVS control. The directory must contain exactly what you want in your new module, and have the same name as the module. Remember to remove any files you don't want under CVS control (e.g. intermediate compiler files)!
  2. Right click on the directory and select CVS/Make New Module...
  3. Fill in the information to specify which repository you want to put the module in, then click OK.

CVS lacks good support for restructuring a project file hierarchy, so you save yourself a lot of trouble if you spend some time planning the module layout in advance.

Be aware that CVS treats empty directories as non-existent. If you want to add a directory in which you have neither files nor subdirectories, you will have to create a dummy file in it. We suggest that you create a file named README.txt, which contains a short description of what this directory is for.

TortoiseCVS creates modules 'in-place'. This is different to the import method used by other CVS clients. Behind the scenes, TortoiseCVS does an import followed by a checkout.

[ CVS Doc: "Starting a project with CVS" ]

Branching

One of the features of version control systems, is the ability to isolate changes onto a separate line of development. This line is known as a branch. (See What branches are good for in the CVS documentation.)

To create a branch, do the following:

  1. Select the directory or files that you want to branch.
  2. Click the right mouse button on the selction, and choose CVS/Create Branch...
  3. In the Branch: input field, enter a tag name that you want to use on your branch. See Tagging Files with a Label to learn what characters are valid in a tag.
  4. Press the OK button.

Now a new branch with the given name is created in the repository. Note: The branch is created in the repository only. To start working on the newly created branch, you have to do what is described in Selecting a Branch to Work on.

[ CVS Doc: "Branching and merging" ]

Selecting a Branch to Work on

To start working on a branch instead of the default development line, you have to bind your local copy to the branch. This is needed to make sure that actions such as updates, commits etc. work on the branch rather than on the main line of development.

To move your local copy to another branch, do the following:

  1. Select the top level directory of the project. (If you know exactly what directories and files are part of the branch, you may select these instead.)
  2. Click the right mouse button on the selection and choose CVS Update while holding down the CTRL key.
  3. In the Get Tag/Branch/Revision field, enter the tag name of the branch you want to switch to.
  4. Press the OK button.

TortoiseCVS will now do the necessary updates to your working copy and move it to the desired branch. The updating may include adding or removing files.

CVS puts what is known as sticky tags on the files that are affected by the branch. To remove the sticky tags and thus go back to the main development line, follow the description in Going Back to the Main Line of Development.

[ CVS Doc: "Accessing branches" ]

Merging from a Branch

When you are satisfied with the changes you have done on a branch, you may want those changes to be available on the main line of development. Incorporating changes from one branch to another, is known as merging. To merge from a branch, do the following:

  1. Move your local copy to the branch you want to merge the changes into. See Selecting a Branch to Work on or Going Back to the Main Line of Development.
  2. Select the top level directory of the project. (If you know exactly what directories and files are part of the branch, you may select these instead.)
  3. Click the right mouse button on the selction, and choose the CVS/Merge... menu item.
  4. In the Branch to merge from input field, enter the tag name of the branch you want to merge from.
  5. Press the OK button.

Any changes on the branch will now be merged into your local copy. You will probably also want to commit the merged files back to the repository, as described in Sending Your Changes to CVS.

Important note: The merge given above will try to merge changes from the start of the branch. If you do the operation a second time (to merge changes done to the branch after the last merge), merging from the start of the branch is not what you want, and it will most likely get you into trouble. To get around this problem, you should give the branch a new tag after every merge, and use the new tag when naming the branch for subsequent merges.

[ CVS Doc: "Merging an entire branch" ]

Going Back to the Main Line of Development

If you want to stop working on a branch and move your local copy back to the main line of development, you have to make TortoiseCVS remove all sticky tags. To remove the sticky tags, and thus update your local copy to the main development line, do the following:

  1. Select the top level directory of the project. (If you know exactly what directories and files are part of the branch, you may select these instead.)
  2. Click the right mouse button on the selction, and choose CVS Update while holding down the CTRL key
  3. Click the Reset sticky tags checkbox.
  4. Press the OK button.

TortoiseCVS will now update your local copy so it matches the current main line of development. The branch you were on still exists in the repository, and you may return to it as described in Selecting a Branch to Work on whenever you want to.

[ CVS Doc: "Sticky tags" ]

Appendix A: Terminology

The terminology used in the CVS documentation, and thus also in TortoiseCVS, may differ from terminology used in other source repository systems. In an attempt to avoid confusion, we provide a short list of the most essential terms.

Checkout
Normally used to describe the first retrieval of an entire module from the repository.
Commit
Sending your modifications to the repository.
Export
Refers to extraction of an entire module from the repository, without any CVS administrative files: Exported modules will not be under CVS control.
Import
Normally refers to the process of creating a new module in the repository by sending an entire directory structure.
Module
A directory hierarchy. A software project normally exists as a single module in the repository.
Release
The version of an entire product.
Revision
The version of a single file.
Tag
A symbolic name given to a set of files at a specific time of development.
Update
Get other users' modifications from the repository. Updates the local copy only.

For the entire story of "revisions", "releases", "versions" and "tags", see chapter 4 of the CVS documentation.

Appendix B: How CVS Differs from Microsoft Visual Source Safe

CVS and WinCvs differ from Visual Source Safe (VSS) in many ways. The most apparent difference may be that CVS does not require users to lock the files they are working on, as VSS does by default. In fact, the CVS documentation even encourages users not to use file locking. In the rare occation where several people have changed the same file at the same time, CVS will normally be able to merge their changes. If two or more developers have changed the same few lines, CVS will report a conflict, insert directives in the file, and leave it to the developers to decide what to do. Such conflicts are very rare, as they normally occur as a result of lacking communication between the developers (eg. two people trying to fix the same problem).

Another important difference is that VSS gives you a server view, while TortoiseCVS shows a client view. In practice this means that, unlike VSS, TortoiseCVS will not tell you about changes in the repository until you do an update, or explicitely query the status of selected files. Changes reported by TortoiseCVS reflect modifications done by you after the last checkout, update or commit.