[1. Introduction 3](#introduction)

[1.1 References 3](#references)

[1.1.1 CVS 3](#cvs)

[1.1.2 Software Configuration Management
3](#software-configuration-management)

[2. Terminology 3](#terminology)

[2.1 Branch 3](#branch)

[2.2 Check-In 3](#check-in)

[2.3 Check-Out 4](#check-out)

[2.4 Codeline 4](#codeline)

[2.5 Commit 4](#commit)

[2.6 Configuration Item 4](#configuration-item)

[2.7 Merge 4](#merge)

[2.8 Update 4](#update)

[2.9 Version 4](#version)

[2.10 Working Copy 5](#working-copy)

[3. CVS Fundamentals 5](#cvs-fundamentals)

[3.1 Introduction 5](#introduction-1)

[3.2 Optimistic vs. Pessimistic Locking
5](#optimistic-vs.-pessimistic-locking)

[3.2.1 Optimistic Locking 5](#optimistic-locking)

[3.2.2 Pessimistic Locking 5](#pessimistic-locking)

[3.3 Tagging 6](#tagging)

[3.4 Branching & Merging 6](#branching-merging)

[3.4.1 Branching 6](#branching)

[3.4.2 Merging 6](#merging)

[3.4.3 Best Practices 7](#best-practices)

[3.5 Command Summary 7](#command-summary)

[3.5.1 Connecting to cvs 7](#connecting-to-cvs)

[3.5.2 Import your project into cvs 8](#import-your-project-into-cvs)

[3.5.3 Create a local working directory (checkout)
9](#create-a-local-working-directory-checkout)

[3.5.4 Add new files to the repository
9](#add-new-files-to-the-repository)

[3.5.5 Edit files and commit changes 9](#edit-files-and-commit-changes)

[3.5.6 Update your working copy 9](#update-your-working-copy)

[3.5.7 Create a Tag 10](#create-a-tag)

[3.5.8 Create a Branch 10](#create-a-branch)

[3.5.9 Merge the specified branch into your working copy.
10](#merge-the-specified-branch-into-your-working-copy.)

[3.6 Command Options 11](#command-options)

[3.7 Conflict 11](#conflict)

[3.7.1 Overview 11](#overview)

[3.7.2 Resolution 12](#resolution)

[4. Patterns 12](#patterns)

[4.1 Mainline 12](#mainline)

[4.1.1 Purpose 12](#purpose)

[4.1.2 Implementation 13](#implementation)

[4.2 Active Development Line 13](#active-development-line)

[4.2.1 Purpose 13](#purpose-1)

[4.2.2 Implementation 13](#implementation-1)

[4.3 Codeline Policy 13](#codeline-policy)

[4.3.1 Purpose 13](#purpose-2)

[4.3.2 Implementation 14](#implementation-2)

[5. Tools 14](#tools)

[5.1 Cygwin 14](#cygwin)

[5.2 WinCVS 14](#wincvs)

[5.3 TortoiseCVS 14](#tortoisecvs)

[5.4 KDiff 14](#kdiff)

[5.5 Guiffy 14](#guiffy)

[5.6 Eclipse 14](#eclipse)

# Introduction

This document will provide an introduction to CVS, and discuss some best
practices for using it. We will introduce some common Software
Configuration Management Patterns and provide guidelines on how to
implement them using CVS.

## References

### CVS

Cederqvist, P., *Version Management with CVS*.
(<http://www.cvshome.org/docs/manual/>)

This is the "official" manual for CVS. It covers both administration and
usage of CVS. It has an appendix of CVS commands and all their options.

Fogel, K., and M. Bar, *Open Source Development with CVS*.
(<http://cvsbook.red-bean.com/>)

Also known as the "Red Bean" book. It also covers both administration
and usage, and has a helpful FAQ/troubleshooting section. This book
covers much the same material as above, but is primarily useful for its
chapters on using CVS for open-source development.

### Software Configuration Management

Appleton, B., S. Berczuk, R. Cabrera, and R. Ornstein, *Streamed Lines:
Branching Patterns for Software Configuration Management*.
(<http://www.cmcrossroads.com/bradapp/acme/branching/branch-creation.html>)

Berczuk, S. P. and B. Appleton, *Software Configuration Management
Patterns*, Boston: Addison Wesley, 2003

These are both excellent sources for discussion of common SCM patterns
and when they are applicable.

Leon, Alexis, *Software Configuration Management*.

# Terminology 

This section introduces some common SCM terms.

## Branch 

A separate line of development within a version control system. The
purpose of branches is to isolate large-scale changes that affect
multiple files and must be committed atomically, rather than piece-meal.
Also referred to as a codeline.

Scenario: You release version 1.0 of your product, and continue on with
development of version 1.1, targeted for release in a month. After a
while with 1.0, your customers call and complain about a fatal bug. So
you check out release 1.0 and find the bug. However, the current
versions of the source file are not stable enough to create a bugfix
release from the tip of the repository, so you need to create a branch
consisting of all the files in release 1.0, fix the defect in that
branch, and then either merge them back into the trunk, or leave them
isolated.

## Check-In

Check-in doesn't really mean anything in CVS, although it is often used
as a synonym for commit. Under other version control systems, check-in
means to save your changes and unlock the file so other can edit it.

## Check-Out

Check-out means something different in CVS than in other version control
systems. In CVS terminology, check-out means to create a local working
copy of the repository. Under other version control systems, check-out
means to lock a particular file for editing.

## Codeline

See branch.

## Commit

The act of merging changes from a developer's private workspace into the
repository. CVS will warn you of any conflicts between your copy and the
repository copy. If the repository version has changed (another
developer committed changes after you started editing), CVS will warn
you that the commit can't continue because your version is out of date.
In that case, you need to perform an update first, to merge repository
changes into your local copy, before you can commit yours.

## Configuration Item

Any resource that is being held under configuration control.

## Merge

The act of moving changes from one branch to another (or, more strictly
speaking, from one version of a file to another). Most merging
strategies are based strictly on changed lines within a file, and thus
only work with text files. Binary files, since they don't contain
'lines' are harder to merge, and most systems will simply store another
entire copy. Version control systems that use a merging strategy will
only keep a single version of the file, and a record of all the changes
that have accrued over time. Thus, an earlier version of the file is
obtained by getting the latest version, and applying the changes (or
deltas) to it in order.

Although we commonly think of merging as a special activity that closes
the loop on a branch (bringing it back to the trunk), merges are
occurring constantly in tools like CVS. Every time a commit or update
occurs, CVS merges the developer's working copy version with the
repository version. Merge headaches are largely a function of the
semantic drift between the two versions being merged, which itself is
largely a product of the time lag between commits.

Strictly speaking, CVS performs three-way merges: the working copy file,
the repository file, and their greatest common ancestor. In many cases,
the greatest common ancestor is identical to the repository version of
the file, in which case there will never be any conflicts.

## Update

Update is essentially the opposite of commit. It will update your local
working copy with any new changes that have been committed to the
repository. CVS will never overwrite your local changes. If there is a
conflict between your local changes and changes that have occurred in
the repository, CVS will back up your version and create a 'conflict
file' that highlights the areas of conflict between the two versions.
Working directly with a conflict file can be difficult if you are not
used to it. There are open source tools (KDiff, Eclipse, for example)
that have much nicer conflict resolution support.

## Version

Very generically, a version is an instance of a configuration item that
is in some way different from other instances of that configuration
item. Thus a particular file might exist in a number of different
versions in the repository, each with a unique identifier that allows it
to be distinguished from all other versions. Upon commit, CVS
distinguishes the new version of the file by incrementing its version
number by 1. Thus the first version of a file is 1.1, the next 1.2, and
so on.

## Working Copy

The working copy of a file refers to a developer's local version of a
file that is being managed in the version control system. The working
copy is effectively isolated from the repository version until an update
or commit operation is performed.

The terms working directory, workspace and sandbox are equivalent.

# CVS Fundamentals

## Introduction

CVS, like other version control systems, allows the developer to isolate
his workspace (or working copy) from the activities of other developers
in order to give him control over when and how his environment changes.
For practical purposes, this means that the developer controls when to
integrate changes from other developers into his workspace, providing
stability for ongoing development operations. There is no guarantee,
however, that code that works within a developer's workspace will work
once all other changes have been integrated, so developers should
integrate new code into their workspace as often as possible. Generally
speaking, the longer the delay between commits or updates, the greater
amount of semantic drift between versions, and the likelier there is to
be a conflict.

## Optimistic vs. Pessimistic Locking

Although these terms are usually used in reference to database
management systems (DBMS) (specifically, referring to when the DBMS will
'lock' a particular table to prevent concurrent access to the same
data), the concepts are equally applicable to source code control
systems. Berczuk and Appleton have a particularly good discussion of the
issues and the positives and negatives of each approach. CVS uses an
optimistic locking strategy, which means that files are not locked until
committed back to the repository. Pessimistic systems allow (or force)
developers to check-out a particular file before they can edit, and
while it is checked out, no one else may change it.

### Optimistic Locking

Optimistic locking strategies within version control systems are also
known as Copy-Modify-Merge strategies. In such a strategy, each
developer has their own local copy of a file which they may edit to
their heart's content. When they are prepared to commit their changes to
the repository, the version control system will merge their changes with
the version in the repository to create the new version. If another
developer has made changes, CVS will notify you that your working copy
is out of date, and will require you to update first (updates will never
overwrite your local changes; at worst, you will end up with a conflict
file and be required to do some reconciliation). Merging usually
proceeds transparently, unless there have been incompatible changes
(edits to the same line, for example). In those cases, CVS will notify
the committer of the problem and allow him an opportunity to reconcile
the changes and recommit. The downside to this approach is when there
are complicated merges; it is often easier to redo one set of changes
than to spend the time reconciling. However, there are patterns that can
help reduce the likelihood (or at least the complexity) of conflicts.

### Pessimistic Locking

Pessimistic locking strategies require developers to check out a file
from the repository before they may perform any edits. While a file is
locked, only the developer who has it checked out may edit it. This
usually eliminates the problem of a conflict during check-in, since no
one else could have made any changes. The weakness with such a strategy
is the same as it is in database management systems; namely, that there
may in reality be no contention between edits (as when the two editors
are working on different parts of the file). In these cases, locking a
file slows down one developer. It is also a common occurrence that a
developer would forget to release the lock, and leave other stranded for
an indeterminate period of time, unless they 'steal' the first
developer's lock, which is itself a problem.

## Tagging

Upon committing a file to the repository, CVS will automatically assign
a version number to it (by the simple expedient of incrementing the
current version number by 1). However, it's often helpful to assign tags
to your artifacts to identify them in other meaningful ways. For
example, version 1.1 of your software includes dozens of files, each
with a specific version. In version 2.0 of your product, there are some
new files, some that were deleted, many that have changed in some way,
and probably even a few that have not changed. But unless you spent the
time to write down the specific version numbers of each file that went
into each version of your product, there is no way to know which
versions went into which release. By applying a tag (version_1_1) to
your repository, you can mark those files (actually, specific versions
of those files) as belonging to a specific release. At some later date,
you can retrieve those files by specifying a tag, and thus can reproduce
a snapshot of your repository at any point of time.

To summarize, tags apply to all the files in your repository, and group
together arbitrary versions of your files. Files can have as many tags
as you'd like; the only requirement is that they be unique. Tags by
default attach to a specific version of a file, but it is possible to
make them 'sticky'. This means that the tag will move to the latest
version upon commit.

Tags are used to denote releases, stable milestones, variants, and
branches (more on this below). All things being equal, it is better to
have too many tags than not enough.

## Branching & Merging

### Branching

Branching creates an isolated codeline, allowing your project to evolve
along parallel lines. The branch is identical to the trunk that spawned
it at the point at which the branch was created. Essentially, your
project can support multiple, independent variants of your files, each
of which is under active development at the same time. Release branches
are a common strategy. When your software is ready to be released to the
public, a branch is created that includes all the files in that release.
Development of the next version occurs along the trunk, but any defect
fixes to the released version occur in the branch. This allows you to
isolate bug fixes from ongoing development activities. Consider the
alternative: without branching, delivering a bug fix is much more
complicated. If development for the next version has continued in the
trunk, you may have introduced instability or new features that you
don't want to deliver with the fix. Task branches can isolate
potentially destabilizing activities so as not to interfere with other
development efforts (a common reason to create a task branch might be to
isolate a complicated refactoring operation from the rest of the ongoing
development operations).

Branches are created using a special type of tag, called a branch tag,
which is a sticky tag.

### Merging

Very often, changes are made in a branch that you want to be included in
the trunk. CVS allows you to merge a branch back into its spawning
branch. In the scenario above, you may want to merge any bugfixes from
your release branch back into the main development line so they don't
come back to haunt you in your next release. As was noted above with
file merges, conflicts are more likely the longer the branch has gone
without a merge. Merging branches is conceptually identical to
individually merging all the files in the two branches. Any conflicts
will be highlighted, and you will be given an opportunity to reconcile
them.

### Best Practices

Best practices for branching and merging are easily summarized as
"branch rarely, merge often". There are good reasons for branching, but
you should make sure you know why you're creating a branch and what
purpose it will serve.

-   Minimize the number of branches active at any one time. The more
    branches under development at the same time, the more likely they
    are to conflict when they are merged back into the mainline or
    trunk. In practice, the best way to accomplish this is to merge
    branches as often as possible (when the branch is at a stable
    point).

-   Minimize the complexity (depth) of your branching scheme. Only
    rarely should you ever branch from a branch. Usually, it's best to
    only branch off the mainline, and merge changes back in as often as
    possible.

-   Use consistently named tags to mark all branch and merge events.
    When a branch is merged multiple times back into the trunk, having
    tags at all the merge events helps minimize conflicts.

-   Adhere to a well-understood naming convention for tags. For example,
    branch tags should include a descriptive name that describes the
    purpose of the branch, plus a suffix indicating that it is a branch.
    Non-branch tags should follow some similar convention. Non-branch
    tags that are paired with branch tags should have some indicator of
    which branch they are paired with (example : 'root-of-\<\<branch tag
    name\>\>).

-   Every branch should have an owner (including the trunk), whose job
    it is to understand the purpose of the branch, be responsible for
    merging back to the trunk, establish the working policy for the
    branch, and to document deviations from the policy.

## Command Summary

This section is not intended as a tutorial to CVS; either the Cederqvist
or Fogel books referenced above are excellent resources. This section
introduces the most commonly used CVS commands. Note that it does not

### Connecting to cvs

:\<protocol\>:\<user\>@\<host\>:\<port\>:\<repository_root\>

Please note the positions of the colons; they are required. If you are
using the command-line CVS client, you can define the environment
variable CVSROOT using the form above. GUI clients, such as TortoiseCVS
(<http://www.tortoisecvs.org/>), will provide a graphical interface for
entering the information.

![](media/image1.png){width="4.885416666666667in"
height="5.677083333333333in"}

-   Protocol: the connection protocol to use. This will usually be
    pserver or ext, although as you can see, CVS supports a number of
    protocols.

-   User: your user name. This is provided by the SCM Administrator.

-   Host: the machine where the repository is located. For NCICB
    development, this is cbiocvs2.nci.nih.gov.

-   Port: this can usually be left blank, unless the server has been
    configured to use a port other than the default (2401).

-   Repository root: this is the filesystem path on the server where the
    repository is located.

-   Module: not strictly part of the CVSROOT, but mentioned here because
    it appears in the dialog box above. This is the name of the module
    you want to check out of the repository. CVS will look for all the
    files stored in \<repository_root\>/\<module\>.

### Import your project into cvs

cvs import --m "message" \<module\> \<vendor-tag\> \<version-tag\>

This is as good a place as any to discuss the differences between text
and binary files. CVS treats them differently internally. Binary files
can not be diffed and merged (see discussion above) like text files. CVS
by default converts line endings in files to the form appropriate to the
operating system on the client machine, and also by default supports
keyword expansion (see below). If you are using the command line client
to perform imports, CVS will assume that all files are text and that you
want keyword expansion on. It is possible to change this later, but keep
it in mind when performing an import via the command line. If you forget
to change the file's setting, you may get odd results.

CVS has a special list of keywords that you can insert into a file that
will automatically get expanded on commits or updates. The most commonly
used are \$Author\$, \$Date\$, and \$Revision\$. For binary files,
keyword expansion should be turned off (with the --kb switch).

### Create a local working directory (checkout)

cvs checkout \<module\>

\- or -

cvs checkout --r \<\<BRANCH_NAME\>\> \<\<MODULE_NAME\>\>

The second version will checkout a specific branch, 'moving' your
working copy to that branch. Both of those versions of the command
assume that you have defined the environment variable CVSROOT as
described above to point to the correct repository. If not, you can pass
the entire CVCSROOT on the command line with the --d switch.

### Add new files to the repository

cvs add \<files\>

If you want to specify the keyword substitution mode, rather than using
the default, you can specify it on the command line with the --k\<mode\>
switch. The most common modes are 'kv' which turns on key-value
substitution, 'o' which turns it off, and 'b' which turns it off and
tells cvs that the file is binary.

### Edit files and commit changes

cvs commit --m "log message" \<files\>

Commit any changes in your working copy back to the repository. If
another developer has made changes to any of the files that you are
committing, you will get an 'out of date' error from cvs and will need
to perform an update first. The \<files\> parameter is optional. By
default, cvs will commit all files in the current directory and all
subdirectories, unless you specify the --l parameter (local directory
only). The log message is required, however. If you forget, cvs will put
up a dialog box to remind you to enter a comment.

A note on log messages: every time you commit a file, you should enter a
log message that describes succinctly what you did to the file and why.
This is necessary for auditing and traceability purposes. CVS has been
configured to require a log message on all commits.

### Update your working copy

cvs update \<files\>

\- or -

cvs update --r \<\<BRANCH_NAME\>\>

The second version updates your working copy with the files in the
specified branch. This form of the command simply 'moves' your local
working directory to the branch specified, but doesn't merge local
changes. CVS will warn you if there are changed files in your current
working directory that need to be committed. If you are intending to
merge changes from the specified branch into your local working copy,
use the --j form discussed below.

### Create a Tag

cvs tag \<\<TAG_NAME\>\>

Please refer to the discussion above for tag best practices. It is
possible to move a tag using the --F switch, or to delete a tag with the
--d switch, but you should not use these options casually. Moving a
release tag after a release has been created can create confusion if you
ever need to recreate that particular tagged version later. Similarly,
deleting a tag will make it impossible to recreate the version that the
tag denotes.

### Create a Branch

cvs tag --b \<\<BRANCH_NAME\>\>

As you can see from the format of the command, branches are created with
a special form of tag, called a branch tag. Branch tags are 'sticky',
meaning they move to the latest version of the file upon commit. To
actually begin working on that branch, you will need to use one of the
update or checkout commands defined above.

### Merge the specified branch into your working copy.

cvs update --j \<\<BRANCH_NAME\>\>

\- or -

cvs update --j \<\<TAG_NAME\>\> -j \<\<BRANCH_NAME\>\>

cvs update --j HEAD

cvs update --j \<\<TAG_NAME\>\> -j HEAD

The second version merges only the changes that have occurred since the
first tag name. You will use this syntax when you have already merged a
branch to the trunk, but have additional changes you wish to merge[^1].
CVS will complain if you try to re-merge changes that have already been
merged, so immediately after merging a branch, you should re-tag the
merge point with another tag[^2]. The final two examples show how to
merge changes from the main trunk into a branch, using the special tag
HEAD, which always represents the trunk of your repository.

You probably won't ever use the last two versions of the update command.
If you have created a version branch, you probably won't want to merge
changes from the trunk onto it because the trunk may be unstable or may
include changes you don't want to get patched into the release. If there
are changes in the trunk that you need to make on the branch, it may be
a better strategy to make the changes manually, which guarantees that no
unexpected changes find their way into the release branch.

## Command Options

Please see Cederqvist for the expanded list of command options. This
section is only intended to document the most common ones.

CVS commands look like :

cvs \[global_options\] command \[command_options\] \[command_args\]

The most common global options are

--d root \[*root* specifies the CVSROOT to use\]

-n \[do not change any files\]. This will give you a preview of what
your command will do, without actually changing anything.

-r \[make new working files read-only; used with checkout\]

-v \[print version information\]

-w \[make new working files read-write\]

-H, \--help \[print a help message\]

## Conflict

### Overview

This is as good a place as any to talk in more detail about conflicts.
This seems to be a major source of concern for most developers,
especially those who are used to version control systems with exclusive
locking. Conflicts occur when two developers modify the same line(s) of
code. In those cases, CVS is designed to fail conservatively; that is,
it will not try to guess which change to keep, but will immediately warn
the committer and let him sort it out. Otherwise, you won't ever know
that someone else edited the same file. Conflicts are essentially only
caught during updates. If you try to commit a file that someone else has
edited, CVS will warn you that the 'up-to-date check failed' for the
file, and you will have to perform an update first. The update will
merge the most recent changes in the repository with your working copy.
If there are any conflicts, CVS will backup your version in your working
directory (by convention, it will be renamed to
**.#\<filename\>\<version\>**), and create a conflict file in its place.
The conflict file is, more or less, the output of the diff command on
Unix. Unless you're comfortable working with that format, there are
tools (kdiff3, guiffy, or the Eclipse client) that will provide a
friendlier view and line-by-line merge support.

Note that CVS will never overwrite your changes when it performs an
update, so you should never fear updates. Also note that even a tool
that allows you to do exclusive locking and editing can create conflicts
that will have to be resolved, if it supports branching. Since branches
allow files to evolve along parallel lines, there is always the
possibility of incompatible changes in different branches.

In the scenario below, developers in workspace 1 and 2 each begin to
edit version 1.2 of a particular file. Developer 1 finishes first and
commits her changes, so the new version in the repository is version
1.3. When developer 2 attempts to commit his changes, CVS will complain
that the 'up-to-date check failed', and will force developer 2 to
perform an update. Upon update, CVS will merge two sets of changes (or
deltas) together to create the new version: the deltas between
repository version 1.2 and 1.3, and the changes between repository
version 1.2 and the local version. As was discussed above in the
definition of merging, version 1.2 is the greatest common ancestor of
the two files being merged. After resolving any conflicts, developer 2
can safely commit his changes, creating repository version 1.4.

![](media/image2.png){width="5.992361111111111in"
height="2.5236111111111112in"}

### Resolution

There are two strategies for resolving conflicts, and plenty of tool
support available to make it easier, if you're not comfortable with diff
output. Rather than discussing how to do it with a tool, we will discuss
the higher level strategies.

The easiest option when you encounter a conflict (and the one most
likely to get you in trouble with your fellow developers) is to simply
force your changes into CVS, overwriting the conflicts. As was noted
above, it's only when comparing three versions of a file that conflicts
are even possible, so as long as you're working from the latest
repository version, you can do anything you want. This may be an option
if there are a large number of conflicts and it would take longer to
resolve them than to simply have one of the developers recreate his
changes.

The other option is to reconcile the changes, and the only question is
which developer will do the work, or whether they'll do it together. In
a distributed environment, working together might not be possible, in
which case it usually falls on the developer who discovered the conflict
to resolve it.

Whichever strategy you select, the key is to keep the lines of
communication open. However you resolve it, you should remember that
changes that have been successfully committed to the repository can
never be lost, unless something is done to the repository itself.

\[TBD -- Discuss the various tools, and integrating them with
WinCVS/TortoiseCVS.\]

# Patterns

## Mainline 

### Purpose

To keep the number of currently active codelines to a manageable set and
avoid growing the project's version tree too wide and too dense. To
minimze the overhead of merging. The purpose of a mainline is to have a
« home codeline » on which to do all ongoing development except in
special circumstances. Thus, major milestones (release versions) will be
branched. Ongoing development for the next version will continue in the
mainline. Bug fixes to the released version will occur in the branch,
and any changes that need to be made in the ongoing stream will be
merged back into the mainline.

### Implementation

Branch when necessary, but merge branches back into the mainline often,
and stop using them when they no longer serve a purpose. Use the
branching and merging best practices discussed above. Merge every stable
waypoint along the branch into the mainline, labeling merge points with
a consistent naming convention. Don't branch off a branch.

## Active Development Line

### Purpose

Software development is largely about balancing progress with stability.
This pattern addresses the question: "how do you keep an evolving
codeline stable enough to be useful?" The extremes are well defined and
should be familiar to anyone with any development experience. First, if
someone checks in a broken module, the entire team can be delayed until
it's fixed. At the other extreme, if pre-checkin validation requirements
are too onerous, developers will commit less frequently, and submit
multiple fixes at once, making it harder to back out changes later, and
makes it more likely that another developer may have submitted an
incompatible change in the interim. And stringent pre-checkin
requirements don't guarantee stability, and may provide a false sense of
security. Your changes may be incompatible with the uncommitted changes
of other developers, which may not be immediately apparent[^3].

### Implementation

The key here is to decide how stable your codeline needs to be, which
is, of course, the hard part. Keep in mind that perfection may be a
laudable goal, but it's neither practical nor attainable in a
distributed development environment. The questions you need to answer
are:

-   Who uses the codeline?

-   What is the release cycle?

-   What test mechanisms are in place?

-   How quickly is the system evolving?

-   What are the real costs for a cycle where things are broken?

## Codeline Policy

### Purpose

The codeline policy pattern is meant to provide guidance to developers
to help them determine which branch they should be working in, and what
tests they need to perform before checking in. A release branch and an
active development branch will have different standards for pre-checking
testing. A good rule of thumb to follow when creating branches is to
always branch on incompatible policies. Thus an active development line
may have only a simple pre-checkin test (it must successfully build with
the latest code from the repository), while a release branch may require
that the fix passes the entire suite of regression tests. In such a
case, a branch is clearly warranted.

### Implementation

Decide on and document the policy for the codeline in question, and
determine the owner. This pattern is implemented with branching, which
has been extensively discussed elsewhere in this document. When there is
no longer a reason to support a separate policy, the branch can be
merged back into its parent and allowed to go dormant.

# Tools

## Cygwin

## WinCVS

## TortoiseCVS

## KDiff

## Guiffy

## Eclipse

[^1]: Strictly speaking, the second tag can be any arbitrary tag, and
    doesn't need to be the branch name. In that case, merge will only
    merge changes that have occurred between the two specified tags.

[^2]: This is a good place to move a tag rather than creating a new one.
    For example, you can create a tag of the form
    \<\<BRANCH_NAME\>\>\_LAST_MERGED which you always move after a
    merge. As long as you remember to do so, you will always know which
    changes have already been merged.

[^3]: Consider the scenario where you make changes to your working copy,
    update from the repository to get last minute changes, run your
    tests successfully, and commit your changes. Meanwhile, before you
    commit your changes, another developer updates, tests successfully,
    and commits her changes. The incompatibility between your changes
    will not be apparent for some time, especially if other developers
    fail to update their working copy before running their tests.