Use Version Control tools

Using Version Control is strongly recommended for all non-trivial projects. For projects with multiple developers, Version Control is almost always a necessity. The advantages of Version Control are compelling:

There are many Version Control systems available. Presented below are reminders for typical use for two such tools, CVS (Concurrent Version System) and Subversion. Another widely used tool is Git.

More complete information is available from:

Subversion

Getting Started With Subversion

Common Commands

svn checkout %SVNROOT%/blah/trunk
Checks out the trunk of a project named blah.

svn commit -m "Some message" blah.txt
Commits a change made to a file in the current directory.

svn help <command>
Get help on a command.

svn status -uv
Shows status. Recursive by default. Talks to server for any updates that you haven't seen yet.

svn log -v
View change sets.

Occasional Commands

svnadmin create C:\\my-repos
Create a local repository.

svn import -m "Importing" . %SVNROOT%/blah/trunk
Import project named blah into a repository. Imports the local directory and all of its subdirectories.

svn info
Shows high level information; shows which branch you are on.

svn ls %SVNROOT%
Lists the projects in the repository. Allows you to navigate the repository's tree structure, by the usual drill-down. '-R' is recursive, and shows each file, not just directories.

Branching

svn mkdir -m "Making first release branch" %SVNROOT%/blah/branch
Create a directory for the blah project to hold all future branches.

svn copy -m "Making Release branch" %SVNROOT%/blah/trunk %SVNROOT%/blah/branch/RB-1.0
Create release branch 1.0. Looks like a directory copy operation.

svn co %SVNROOT%/blah/branch/RB-1.0 blah1.0
Check out release branch 1.0 to directory named blah1.0. The working directory is usually beside blah, which contains the main trunk of development.

svn merge -r11:12 %SVNROOT%/blah/branch/RB-1.0
Merging a fix on a release branch into the trunk. Picks up edits between revision 11 and revision 12. Needs a commit afterwards.

CVS

CVS Terminology

CVS Edit Codes

Getting Started With CVS

cvs --help-commands
Lists all CVS commands.

cvs -H update
Displays help for the update command.

cvs -d C:\\sandbox init
Creates a local 'sandbox' repository, on the local file system. Such a sandbox is very helpful for experimenting with CVS. This is a nice feature, since you don't have to set up a server in order to create the repository. For more formal development, however, your 'real' source code will be stored in a server on another host, not on the local file system.

tmp>set CVSROOT=C:\\sandbox
tmp>cvs import -m "Play around with CVS" myproject myproject initial
Create a new project named 'myproject', built from the current contents of your tmp directory (and subdirectories), and place the new project into your sandbox repository.

work>cvs -d C:\\sandbox checkout myproject
Retrieves from the sandbox repository a copy of all files in myproject, and places them into work/myproject. Retrieves the latest version of each file (the HEAD).

Common Commands

cvs status Blah.java
Lists general information about the file, whether it has been edited, it's revision, and what branch it's on.

cvs status -q Blah.java
More concise status listing.

cvs -q update -P -d
Updates your workspace with the latest repository files. Performs a merge. Most merges will succeed, but some will fail, and will result in a conflict. Conflicts must be handled manually.

This is a 'sticky' operation (see above). If your workspace is on the trunk, then you are updated with new trunk files. If your workspace is on a branch, then you are updated with files from that branch.

cvs -nq update -P -d
Compares your workspace with the repository without actually doing the update. Does not write to your workspace. The '-n' option means "don't really do this, just show me the current differences between my workspace and the HEAD of the repository."

cvs -q update -P -d -A
Updates your workspace, and ensures you're updated with the trunk, not a branch.

cvs -q udpate -P -d -r REL_1_0
Updates your workspace with a specific release branch.

cvs commit -m "Some appropriate description"
Commits all edits to all files in and under the current directory.

cvs history -c -u myuserid -D yesterday -z AST
Displays what a specific user id committed yesterday, and displays the result in a specific time zone (AST) instead of Universal Time.

Occasional Commands

work>cvs checkout myproject
Fetches an entire project from the repository, and places it in the local directory named work/myproject.

cvs add Blah.java
cvs commit -m "My new file." Blah.java
Adds a new file to the repository. Note that you need to commit the file before the addition is complete.

cvs add -kb jstl.jar
cvs commit -m "Required library." jstl.jar
Adds a new binary file to the repository. Again, you need to commit the file before the addition is complete.

work>del Blah.java
work>cvs remove Blah.java
work>cvs commit "No longer needed." Blah.java
Deletes a file. This has 3 steps.

cvs history -c -D "2010/01/01" -z AST Blah.java
Displays a history of commits on a given file, after a given date, with date-time output in a specific time zone (AST).

cvs log -d today Blah.java
Shows messages for all commits done today for a given file.

cvs -q log -wmyuserid -d"2010/04/13 13:00:00" -S
Shows messages for all commits done by a certain user, after a given date-time

cvs log -rREL_1_0 -wmyuserid Blah.java
Shows the commit messages for a given user id, performed on a specific branch.

work>rename SolarSys.java SolarSystem.java
work>cvs remove SolarSys.java
work>cvs add SolarSystem.java
work>cvs commit -m "Better name." SolarSystem.java
Renames a file. This has 4 steps.

cvs rtag -b RB_1_0 myproject
Creates a release branch named 'RB_1_0' for a project named 'myproject'. This command is applied to the repository, not to the workspace. A release branch can be created before the release, if desired. Then, each release candidate is built using the head of the release branch. When the release is final, then you apply a regular tag to the release branch, to mark the exact point of release.

cvs tag REL_1_0
Tags the repository files in your BASE -- the unmodified revisions checked out to your local workspace.

cvs diff --side-by-side Blah.java
Shows the differences between your workspace and the BASE.

CVS Quirks

Merging From Branch To Trunk

There are two ways to merge from a branch into the trunk.

cvs -q update -j 1.1.2.2 -j 1.1.2.3 Blah.java
This is usually the preferred method. Note the presence of 2 '-j' options. This means that only the edits that took the file from 1.1.2.2 to 1.1.2.3 are to be merged into the trunk. This is very helpful, because it can avoid the repetition of possible conflicts that may have already occurred during previous merges.

cvs -q update -j 1.1.2.3 Blah.java
This is usually not the preferred style (see above). This merge has a single '-j' option. The implementation of this merge will need to go back to the common ancestor of the trunk and the branch. The problem with this style is how conflicts are treated. If such a merge has a conflict, it can certainly be resolved, just like any other conflict. However, the conflict will resurface again later should you need to perform another merge between the branch and the trunk.

Separate Workspaces For Each Branch

Although there are many variations, it's typical to be working on 2 code streams (sometimes more) :

When working on more than a single branch, it's helpful to be able to switch rapidly between them. It's certainly possible to use a single local workspace to do so, using a 'cvs update' command which specifies the appropriate branch.

However, many find it simpler and more convenient to just use a separate workspace for each branch. Since the update command is "sticky", and remembers the branch from which a workspace originally came from, there's usually no asymmetry between working on the branch and working on the trunk.