Centralized Version Control (CVS, Subversion)
Steven J Zeil
Abstract
Centralized version control stores the history of the code base on a separate server from which copied can be provided to all developers.
In this lesson we will look at the advantages of centralized version control over local control. Particular attention will be paid to the area of collaboration where local locking mechanisms are replaced by after-fact detection and resolution of conflicting changes.
We will look at one of the most influential version control systems, CVS.
Centralized Version Control
rcs kept its repository of history information in the “live” working directories.
-
Each directory of a project had a separate repository.
-
Sharing among team members relied on the rather limited Unix protection scheme.
Centralized version control systems keep a project repository in a location separate from the programmer’s work area.
-
Allows one repository to track a project’s entire directory tree
-
Encourages/requires use of a network-based sharing scheme
- Allowing therefore a more distributed work effort
1 CVS
-
Based on rcs
- Many of the concepts and commands are similar
-
Uses a centralized store
- can be on local or remote machine
1.1 History
-
Check-in and check-out are similar to rcs
- No locks, however
-
By default, scope of commands is an entire directory tree
cvs checkout projectRootDir
makes a copy of projectRootDir in the working directory, checking out the most recent version of everything in the project.
Similarly,
cd projectRootDir
cvs commit -m "Added unit tests"
checks in any changes from the working directory on down.
- Unix nerd alert: I often think of the
cvs doSomething
commands as if they were
find . -type f -exec rcsDoSomething {} \;
Where’s the Repository?
The earlier commands presume that we have, somehow, already established a connection with the repository.
- In practice this is either done via earlier steps or added as additional options to individual commands
Local CVS Repositories
If the repository is on a local file file system,
- you can specify it via
-d
:
cvs -d /usr/local/cvsroot checkout myProject/projectRootDir
or record this info in an environment variable:
setenv CVSROOT /usr/local/cvsroot
cvs checkout myProject/projectRootDir
Remote Repositories
The same techniques (-d, CVSROOT) can be used to specify remote repositories.
-
Instead of simply specifying the path to the repository, give
[:method:][[user][:password]@]hostname[:[port]]/path/to/repository
- Specifying the password in this way is a really bad idea
-
Usually, use
cvs login
to open a session (rather than get prompted for a password on every command).
Connection method: pserver
-
The pserver method is a built-in network connection method with password control.
- Port 2401
-
Falling out of favor
pserver Exmaple
sirius:~/temp/tmp> setenv CVSROOT :pserver:zeil@cvs.cs.odu.edu:/home/cvs/dlib
sirius:~/temp/tmp> cvs login
Logging in to :pserver:zeil@cvs.cs.odu.edu:2401/home/cvs/dlib
CVS password: *****
sirius:~/temp/tmp> cvs checkout AlgAE
cvs checkout: Updating AlgAE
U AlgAE/.project
U AlgAE/AlgAE_layout.odg
U AlgAE/LICENSE.txt
U AlgAE/README.txt
U AlgAE/build.xml
U AlgAE/buttons.gif
U AlgAE/buttons.odg
U AlgAE/jhbasic.jar
U AlgAE/junit-4.10.jar
cvs checkout: Updating AlgAE/AlgAE_screenshot.png
⋮
sirius:~/temp/tmp> ls -ld AlgAE
drwxrwxr-x 11 zeil faculty 1024 Feb 21 13:39 AlgAE/
ssh Connections
If you have ssh access to the machine running the CVS server, you can do
sirius:~/temp/tmp> setenv CVSROOT :extssh:zeil@cvs.cs.odu.edu:/home/cvs/dlib
sirius:~/temp/tmp> cvs checkout AlgAE
The authenticity of host 'cvs.cs.odu.edu (128.82.4.233)' can't be established.
RSA key fingerprint
⋮
Password:
The History Commands
-
checkout: gets an initial copy of what’s on the server
-
update: checks to see if something newer than a local file copy is on the server, and if so, replaces the local copy by the remote one
-
commit: sends any local files that are newer than the server copy to the server as new revisions
-
add: places files that are not currently being tracked by CVS under version control
- does not affect the server until committed
-
import: places a directory tree under version control
-
release: detaches the directory from the CVS server (if no files need to be committed)
1.1.1 Eclipse Integration
Eclipse includes CVS support in its normal distributions.
-
From
Window->Open Perspective->Other...
, selectCVS Repository Exploring
-
Of course, you will need to have access to a repository before you see anything.
Checking Out an Existing Project
Pulling an existing project from CVS into Eclipse is pretty straightforward:
- From the New Project menu, select “Project from CVS”
- Fill in the repository information
- Select the “module” (project)
- if given an option, request the use of the wizard to configure the checked-out project
- Select the “Head”, a branch, a version, or by date
Eclipse Integration: Creating a Project
To add a new project to an existing repository:
-
Set up the project as normal on your local machine
- “Clean” the project of any object code, compiled classes, archives, etc. that are products of the project build are not present.
- This is optional, but saves work later.
- “Clean” the project of any object code, compiled classes, archives, etc. that are products of the project build are not present.
-
Right-click on the project and select
Team->Share Project...
- Fill in the repository information
-
You will eventually be shown a list of files to be committed.
- Review them carefully. If you check in something that you don’t want under version control, it’s virtually impossible to remove later.
- Think carefully about adding the Eclipse .project, .classpath, etc. files to the control set.
Working with History in Eclipse
Right-click on a file or directory and look in the “team” menu
-
Add to version control
-
Commit…
-
Update
-
Synchronize with repository
- Combines commit and update, lets you select which files go in which direction
- Be careful of adding build products to the repository as you commit.
- Exercise the options to “remove from view” or, for a more permanent solution, “Add to .cvsignore”
You might want to put .cvsignore under version control.
-
Tag (name)
-
Show History
Examining History in Eclipse
Right-click on a file or directory and look for
- Compare (local copy) with
- head, specific branches
1.2 Exploration
Branches
- Same as
rcs
Creating Branches
-
Make sure that you have checked in all the latest changes in your current working project.
-
Right-click on the project root directory and select
Team <span>⇒</span> Branch\dots
.-
Enter a name for your branch.
-
Leave “Start working in the branch” checked. Click OK.
-
All the files under that root directory will be marked as belonging to a new branch.
-
As you work on this branch, you can make frequent use of the
Compare With ... Head
option to check for changes in the main trunk that you might want to incorporate into your branch code.
Merging a Branch Back Into the Main Trunk
- Make sure that your copy of the branch is up-to-date, all changes checked in.
- If you want to allow for continued use of the branch after the merge, add a tag on the branch.
Right-click on a project with an up-to-date copy of the branch, and select “Team ⇒ Tag as Version … ”
1: To begin the actual merge, start with an up-to-date copy of the main trunk (HEAD).
- You may already have one,
- Or you can right-click on the branc project, select “Team ⇒ Replace with ⇒ Branch or Version” and select HEAD.
- This will actually check out a copy of the HEAD, replacing code in the branch.
That should not be a problem, since you made sure that you had checked in all changes in the 1st step. But it is a bit disconcerting, so I prefer to simply work from s separate project that is already checked out from the HEAD branch.
You might consider placing a “tag” on the main branch (HEAD) to mark the spot on the branch just prior to the merge. that way, if you make a mistake when resolving conflicts (see below), it will be easy to get back to the current version. To place a tag, right-click on a project with an up-to-date copy of the HEAD, and select “Team ⇒ Tag as Version … ”
- This will actually check out a copy of the HEAD, replacing code in the branch.
2: Right-click on the HEAD project and select “Team ⇒ Merge … ”.
- You will be asked what branch you want to merge with. Select the appropriate branch to be merged into HEAD.
- You will be asked to supply the common base version from which the branch was split - usually Eclipse will guess this correctly.
- You can also decide whether to have CVS automatically make any non-conflicting changes or to let you preview them.
- No matter what choice you make here, conflicts will still be presented to you for resolution.
3: CVS will compare the checked-in copy of the branch against the files in your local HEAD project.
- You should see the familiar Synchronization view, in which you can preview changes and resolve conflicts.
- The goal of this process is to leave you with a local copy of all the desired changes.
This is not a commit of the merged changes to the HEAD branch.
4: Having resolved all changes, you now have a local copy of the project, associated with the HEAD branch in CVS, with a merged copy of code from the former HEAD and from the other branch.
- It has not been committed to the repository yet.
- You can test it out, and then decide whether to commit the changes into the HEAD.
1.3 Collaboration
Resolving Conflicts
During synchronization, changes are categorized as
- Incoming: files that you have not edited your local copy (since it was last synchronized with the repository) but for which a revision has since been checked in.
These presumably need to be updated
.
- Outgoing: files that you have changed (since it was last synchronized with the repository) and for which no revisions have been checked in.
These presumably need to be committed
.
- Conflicts: Files that have been changed in your local directory and that have had revisions checked in to the repository.
These presumably need to be merged
The Conflict Editor
-
It allows you to view the differences between the two versions and decide whether
- to keep the local version of each block of changed lines or
- to replace by the repository’s version.
-
You can save the merged file and then “Mark as Merged”, which moves it from the “Conflicts” status to “Outgoing”
-
Or you can “Override and Update”, which indicates that you are abandoning your local changes and changing the file’s status to “Incoming”
2 Subversion
Subversion
Subversion (a.k.a. svn) is a later version control system based on the same centralized model as CVS.
-
For the most part, working with it is not all that different from CVS.
-
It rose to popularity in the open source community in part because of some useful tools for making read-only versions available on the web.
- In fairness, this is not due to any particular strength of Subversion.
2.1 History
Differences between CVS and Subversion w.r.t. history:
-
Subversion uses simpler revision numbers
-
Subversion tracks file and directory creation, deletion, renaming
2.2 Exploration
2.2.1 Subversion Doesn’t Understand Branches …
Subversion does not implement a distinct mechanism for branching.
-
Each revision (and each checked-out local copy) “knows” its parent revision number.
-
Revisions can be checked out into distinct local directories from where their parents were located.
-
Remember – Subversion tracks moving/renaming of files
-
… but it Does Branches Anyway
-
“Branches” are kept in a separate directory from the trunk.
- But a checked-out version of a branch “knows” which revision it came from
- whether that revision is on the trunk or on the branch
- But a checked-out version of a branch “knows” which revision it came from
-
“Merging” is a general operation between revisions
- So it can be done as a regular merge to adopt changes made in the branch as part of the trunk
- or as a “sync merge” to add revisions from the trunk to the branch
Is This an Improvement?
I can’t decide if Subversion’s approach to branches is inspired or lazy.
The two are not, of course, mutually exclusive.
-
Branching and merging is CVS is just complicated enough that it’s easy to mess up.
- Luckily, you can always recover from mistakes by checking out an older version and re-committing.
-
In svn, you typically check out the trunk or a branch – not the whole repository.
2.2.2 Subversion Doesn’t Understand Tags …
- Tag name becomes the folder name within the Tags directory.
2.3 Collaboration
No real differences between CVS and SVN
- Conflicts can arise a check in and must be manually resolved.
2.4 Eclipse Integration
- Not part of the regular distrbution
has to be installed as a plug-in
- Two plugins are available
- Subversion is older and is an “incubating” part of the Eclipse project
- But has been in that status for a long time
- Subclipse is newer, seems to be more aggressively updated
- Installation can be somewhat tricky (on Linux, at least)
- Subversion is older and is an “incubating” part of the Eclipse project
Relies on some non-Eclipse libraries that must be installed separately.
-
Sometimes a period of instability after Eclipse updates before either plugin becomes usable.
-
Google for instructions on either plugin