Spin Versioning and Branching

December 19, 1994
Updated January 24, 1995


The helpful CVS FAQ has lots of hints and Version Management with CVS is pretty thorough.

Here is the CVS Web Page on the net.

The man pages are in the contrib man page directory (add that to your MANPATH). The info pages are in the contrib info directory.

We were using the btools package from the OSF ODE system. We are still using build technology of the OSF ODE system, including build, odemake and mksb.

cvs is in the contrib bin directory. To use cvs put the CVS root directory in your CVSROOT environment variable.

Using CVS for Spin files

See the releases page for the list of SPIN revisions.

Starting out

The exception.c example.

Use cvs checkout -r revision file to get the files on which you want to work. revision is the full tree you are backing from (see Revisions above). file can also be a directory name which will get all files in the directory tree. Run this in your sandbox/src directory giving file as the relative path from src, as in mk/kernel/alpha/trap.c.

Making your branch

First setup a set up a sandbox using mksb. CVS replaces the btools like bco, bci and bcs. We still have sandboxes, shadowing and build from ODE which CVS knows nothing about.

To do RCS-like operations on your files without affecting anyone else, make your own branch. The new branch will be a temporary branch that is merged back into the mainline when the next release is merged.

Getting a file:

	cd becker/work/src
	cvs checkout -r release-4 mk/kernel/alpha/trap.c
You may now edit, remove, or otherwise mangle the file without affecting anyone else or the RCS file where it came from

Committing changes requires you have your own branch:

	cvs tag -b r4-becker mk/kernel/alpha/trap.c
	cvs update -r r4-becker mk/kernel/alpha/trap.c
By convention make branch names like r4-becker where r4 corresponds to the release from which your files were checked out.

Now you can procede with an edit/commit cycle in your own branch.

	edit
	cvs commit -m "rcs log message"  mk/kernel/alpha/trap.c
	edit
	cvs commit -m "rcs log message"  mk/kernel/alpha/trap.c
	...

Use cvs stat -v file to see all the revisions and branches associated with a particular file. Revision tags are static unless you force them to move. Branch tags always refer to the latest file on the branch.

At merge time, the merger combines everyone's branching into a new release so understand how merging happens before getting fancy with branching.

Adding a new directory

When a new directory is needed in the src structure, it also needs to be added to the CVS repository. Also set the current branch (aka sticky tag) to the trunk.
	mkdir dir
	cvs add dir
	cvs update -A dir

Adding a new file

To make sure new files go into the next merge, they are added on the main trunk and then branched. First, add the new file to the trunk:
	create file
	cvs add file
	cvs update -A file
	cvs commit file
Then make your own branch just as above:
	cvs tag -b r4-becker file
	cvs update -r r4-becker file
Now the file can be modified as any other on your branch.

Removing files

When a file is to no longer appear in current or future revisions, use the remove subcommand. The file will be stored in the "Attic" subdirectory in the CVS repository so past revisions can still be fully checked out.
	cvs update -A file
	rm file
	cvs remove file
	cvs commit file

Tags versus Branches

Most cvs operations have a "-r rev" option where rev can be either a branch or a tag. Both branches and tags represent RCS labels stored in the RCS headers in the repository RCS files. It is CVS, not RCS, that intreprets the labels to mean tags or branches.

A branch is a lineage created by cvs tag -b file

A tag is a freeze marked by cvs tag file

Use 'cvs stat -v file' to examine the branches and tags for "file" stat -v shows these labels for mk/kernel/alpha/trap.c:

	r4-loipc                        (branch: 1.3.2)
        release-4                       (revision: 1.3)
        r3-merge                        (revision: 1.3)
        release-3                       (revision: 1.1.1.2)
        release-2                       (revision: 1.1.1.1)
        release-1                       (revision: 1.1.1.1)
        origin-branch                   (branch: 1.1.1)
						.
					       /|\
						|
				"revision:" is a tag.  "branch:" is a branch.
Checkout by tag release-3 will retrieve version 1.1.1.2
	cvs checkout -r release-3 mk/kernel/alpha/trap.c
Checkout from branch r4-loipc will retrieve 1.3.2.x where x is the latest version on that branch.
	cvs checkout -r r4-loipc mk/kernel/alpha/trap.c 

CVS instead of cp to share code

Rather than copying code between sandboxes with cp, you can use cvs to merge other code into your branch. Suppose I make a r4-becker branch for mk/kernel/alpha/trap.c and commit a new version of trap.c with the freeze tag of r4-becker-apr1. To bring this tag into your branch:
	cvs update -j r4-becker-apr1 mk/kernel/alpha/trap.c
If there are conflicts, cvs will mark those areas of the file it failed to resolve with >>>> ==== <<<<< lines.

What update and checkout do

Update and checkout (alias get) are often interchangeable, hence confusing. They will modify your tree, but never ever delete files that are modified. Modified (uncommitted) files are reported as "M filename" and are not deleted.

cvs update -r branch will replace your branch with branch adding and deleting files to make the tree look like branch.

cvs update -j branch will merge the diffs between branch and the trunk into your tree. Previously modified files are affectd as well as untouched parts of your branch. No files will be added or deleted. When branch has new files, you must add those files to your branch with tag -b and update -r as usual.

Weirdness

Ctrl-C
CVS uses the system(3) call to run the RCS commands so Ctrl-C often only kills the subprogram instead of CVS. Use Ctrl-Z to stop it and then kill CVS (kill %).
Path names
Some commands only work on the current directory (add and release). Sometimes you have to give the whole path (mk/kernel/alpha/trap.c) or can work with partial paths (alpha/trap.c) if a CVS subdir already exists the current directory.
Current branch
CVS's idea of the current branch for a particular file is affected by several things. If it thinks all the files in a dir belong to a single branch, new operations will default to that branch. If it sees a mixture or no files at all, the default is the head of the main trunk. The "sticky tag" is the default rev for the -r flag on all the CVS operations. Update -r sets the sticky tag, which is reported by stat -v.

How to merge

First checkout the previous merge. Since it is possible for main trunk commits to have occured, we must merge the head with the old release and see if any files got screwed up. In an empty sandbox/src dir
	cvs checkout -j release-1 mk osf
If the revision labelled release-1 is not the most recent trunk revision of that file, it will have 'M' or 'C' status and needs to be examined. Trunk changes should only be done by the merger.

For everyone's branch,

	cvs update -q -j r1-branchname
Clean merges are marked 'M'. Conflicts you have to resolve are marked 'C'

Now make the merge compile and run, committing as desired to the trunk. Change conf/version.edit in the server and kernel to the new version.

Once the merge works, check it in and label the new release.

	cvs commit
	cvs tag release-2


becker@cs.washington.edu