CVS Notes

Copyright ©2001 by John Cawley III. This document may be freely copied, distributed and archived provided it is copied entire and unmodified and the copyright statement remains intact.

Last modified: 2003-05-04. The current version of this document is available at http://www.Thistlehaven.net/J3. Email comments and questions about this document to j3@pobox.com.

 

CVS Usage Notes:

 

Basic Usage: quick reference to common commands

 

 

Simple Branching: simple branching isn't too hard

 

Hazards in Branching: when you begin to update from the trunk, or to merge into the trunk multiple times, things get strange

 

Complex Branching: some rules of thumb for complex branching

 

 

 

 

 

 

 


Quick Reference for Common Commands:

Create Repository: this is generally done once only, and might well have already been done for you

Import a Project: optional step; allows you to add a project and multiple subdirectories and files in one blow

Check out a Project:
- create a working subdirectory and cd into it, then execute this command
- you may indicate that a specific release be checked out (for recreating past or alternate versions of the project)
- while in this working direcotory, you no longer need to specify the repository as it is "remembered" for you

Determine What Has Changed: since a project was checked out:
- U = Updated in repository since checkout
- M = Modified in checked-out version
- C = Conflict -- updated and modified in incompatible ways
- A = Added
- R = Removed
- ? = Uknown to repository

Add or Remove a File From a Project:
- if a file is added or removed, it takes effect upon the next Check In
- subdirectories may be added
- if you do not specify the -f flag on the remove command, you must have already deleted the file yourself

Check In Project: checks your code in

Tag a Release: assign an English name, under which the current versions of all files will be remembered; can be used to later restore a previous version of the code to a working directory

Export a Project: releases a version (usually tagged) for use, for example for beta testing or production; similar to "co", but without the CVS subdirectory clutter


Simple Branching:

Notes

Overview: the goal of this approach is to keep a trunk that is "clean" (ie always exportable to a production area) and to do subproject work on branches that may become "dirty" for a time; each subproject is branched off the trunk (and not off another subbranch -- this keeps things simpler); when the subprojects are completed (and "clean"), they are merged back into the trunk, which then acquires the features that the subproject added

#1 Tag Prior to Branch: Tag the trunk just prior to the branch for later emergency use. From a working directory created to hold this branch:
cvs -d {PathRepos} co -d . {Project}
cvs tag Start{Subprj}{yyyymmdd}Beg

#2 Create Branch: create the subproject branch. From the branch working directory:
cvs tag -b {SubPrj}
cvs update -r {SubPrj}
cvs tag Start{Subprj}{yyyymmdd}End #
strictly speaking, unnecessary

#3 Updates May Occur on the Trunk: updates may continue to occur on the trunk while the branch is being worked on (eg from other branches being merged upon their completion)

#4 Tag Branch Prior to Merge: this may be needed later for emergencies or for complex branching if this branch must be resurrected; from the branch working directory :
cvs tag Finish{Subprj}{yyyymmdd}Beg

#5 Merge Branch and Tag Trunk at this Point: merge the branch back into the trunk, resolving any conflicts, and tag the trunk for later emergency/complex use; from a trunk working directory:
cvs update -j {Subprj}
cvs ci -m "Finish {Subprj} {YYYY.MM.DD}"
cvs tag Finish{Subprj}{yyyymmdd}End

#6 Note That Branch Deaths Are Soft: note that branches do not die -- they are merely "laid down " when you are done using them and are not picked up again simply because of programmer and project self-discipline

#7 Quick Reference: branch names are generally treated as the tip of that branch
cvs update -j {Tag} this takes all changes from the branch's root to its tip and merges them
cvs update -j {Tag1} -j {Tag2} this takes all changes from Tag1 to Tag2 and merges them
if Tag2 is a branch name, it implies the tip of that branch


Hazards of Branching:

Notes

Overview: when merging a branch into the trunk more than once, care must be taken to not duplicate the modifications from the first merge in with the second merge. Note that this discussion applies also to the mirror image of the situation described -- ie merges from the trunk into the subproject branch behave similarly.

#1: This is the first merge and is accomplished via the following statements:

from the branch working directory:
cvs tag From{Subprj}{yyyymmdd}Beg
(alternately:
cvs tag -r Start{Subprj}{yyyymmdd}End -r From{Subprj}{yyyymmdd}Beg )

from the trunk working directory:
cvs update -j {Subprj}
cvs ci -m "Merged Subprj into trunk, {YYYY.MM.DD}"
cvs tag From{Subprj}{yyyymmdd}End

#2: The second merge cannot consist of all changes from the beginning of the branch to its tip, as part of those hav e already been applied and will cause spurious conflicts if they are attempted a second time. In other words, the following statement will indicate conflicts:

...
from the trunk working directory:
cvs update -j {Subprj} (wrong!)

#3: The correct way to accomplish the subsequent merge is via the following statements:

from the branch working directory:
cvs tag From{Subprj}{yyyymmdd2}Beg

from the trunk working directory:
cvs update -j From{Subprj}{yyyymmdd}Beg -j From{Subprj}{yyyymmdd2}Beg
cvs ci -m "Merged Subprj into Trunk {YYYY.MM.DD2}";
cvs tag From{Subprj}{yyyymmdd2}End


Complex Branching:

Notes

Overview: this diagram illustrates common usage with multiple alternating merges to and from a branch. With this behavior, the changes applied are from the beginning of the merge in the opposite direction to the beginning of this merge.

#1 Merge from subprj: This is accomplished via the following statements:

from the subproject/branch working directory:
cvs tag From{Subprj}{yyyymmdd2}Beg

from the trunk working directory:
cvs update -j To{Subprj}{yyyymmdd}Beg -j From{Subprj}{yyyymmdd2}Beg
cvs ci -m "Merged from Subprj into trunk, {YYYY.MM.DD2}"
cvs tag From{Subprj}{yyyymmdd2}End

#2 Merge to subprj: This is accomplished via the following statements:

from the branch working directory:
cvs tag To{Subprj}{yyyymmdd3}Beg

from the subproject/trunk working directory:
cvs update -j From{Subprj}{yyyymmdd2}Beg -j To{Subprj}{yyyymmdd3}Beg
cvs ci -m "Merged to Subprj from Trunk {YYYY.MM.DD3}";
cvs tag To{Subprj}{yyyymmdd3}End