.pl 29.7c
.nr PO 2.88c
.nr LL 17c
.nr HM 1.5c
.nr FM 1.5c
... .FP Times
... .fp 1 R R.nomath
... .fp 5 CW LucidaSansCW83
.RP
.TL
vcs: Version Control with a Plan 9 Mindset
.AH "Devon H. O'Dell <dodell@sitetronics.com>"
.SA
vcs is a modern version control system providing easily accessible support for
software development features that are commonly ignored in current popular
version control software. This paper discusses its design, usage and
implementation.
.SE
.SC 10
.NH 1
Introduction
.LP
vcs is a modern version control system designed to make use of features
available in the Plan 9 operating system. vcs is built on top of
.CW vac (1),
the Venti archival utility. It is designed to easily work in both distributed
and centralized software development environments and should scale well in
either scenario.
.NH 2
Version Control Models
.NH 3
``Push'' and ``Pull'' Models
.LP
Many modern, popularly used version control systems (such as cvs, Subversion,
and Perforce) use centralized development models. In centralized models,
a repository is stored on a central server where users with access to write to
that repository are able to make changes to that system. This is generally
referred to as a ``push'' model. While this model is suitable for many
software projects, it does not quite fit in with the distributed design of the
Plan 9 OS.
.LP
Distributed versioning systems do exist as well; software such as arch, darcs
and BitKeeper are examples of these. While they do exist, I feel that the
design and licenses attached to them are improper for Plan 9. Additionally,
they assume a system more alike UNIX than Plan 9 is. In distributed systems,
there is generally an ``official'' central repository from which releases
are made, managed by one or more maintainers. Developers and maintainers
create their own private branches of the ``central'' repository and work on
these. When a maintainer feels that a patch in a branch should be
incorporated in the official version of the software, the code is retrieved
into the ``central'' repository. This is called a ``pull'' model.
.LP
Both models have specific advantages for different projects. Push models are
advantageous in situations where sources are controlled and developed in a
controlled environment. Pull models are generally better to work with in
projects with an active lead, but loosely knit developer connections.
.LP
In fact, both the push and pull models operate in a quite similar respect.
Many operations and ideas between the two are shared with a reversed order
of operation.
.NH 3
The ``Slide'' Model
.LP
vcs couples the push and pull concepts into a new model called ``sliding''.
``Sliding'' is the core concept of vcs. Both push and pull operations can
be thought of as slide operations; branching trees is a slide operation.
While not inherently different in operation from either the push or pull
models, the slide model provides several advantages over both:
.IP \(bu
Using the same terminology for both models allows for (slightly) more
verbose commands, which in turn make it easier for new users to learn
the system.
.IP \(bu
Integrating both models to use the same commands allows for projects to
change development models as it is seen fit and for developers to easily
work in many projects with differing development models.
.IP \(bu
Branching code in centralized repositories is often a pain while this
concept is vital for the operation of distributed repositories. By
combining these two models, each one gains the advantages of the other.
.IP \(bu
In practice, both models can be used allowing for private, offline
development, while still maintaining a central repository and controlled
code environment.
.NH 2
Goals of vcs
.LP
vcs is built upon a set of standards from which should never be deviated.
.IP \(bu
Simplicity of design. vcs should be implemented in a simple and
understandable manner. vcs goes about this by simplifying and generalizing
the models used in software control.
.IP \(bu
Ease of use. Nobody wants to spend weeks learning how to use a new version
control system.
.IP \(bu
Speed. It is not a goal to be blazing fast, but vcs should never be
unbearably slow.
.IP \(bu
Security. In controlled, centralized software development environments,
security is premium. Security should not become obtuse, however, and where
possible should be handled by the underlying system (and administrator).
.IP \(bu
Flexibility in a sane way. vcs should never overload the user nor
administrator with options or features. vcs should never box the user nor
administrator into a certain model.
.NH 1
Using vcs
.LP
Before discussing the implementation of vcs, we shall first take a look at
how it works in practice. This process will be discussed from the ground up:
as it would be done when starting a new project.
.NH 2
Deciding on a project model
.LP
Before beginning a repository, it's a good idea to make sure one understands
the differences between the push and pull models and how they relate to
the slide model interface provided by vcs. Although the slide model
implemented by vcs makes this transparent to the user, understanding the
differences in the models will help an administrator guide the contributors
of the project.
.LP
If your project is based upon local developers who will be working on
different parts of the project and should be working in a controlled
setting, you will want to use a push model.
.LP
If you work solely or loosely with others on your project, you will want to
use a pull model.
.LP
If your project is comprised of many local and distributed developers and is
of a significant size, you can benefit from the hybrid model, which allows
for a controlled main repository while allowing any developer the ability to
work on side projects separately from the main branch.
.LP
After a project model has been settled on, it is important to note the
differences in local workspaces. A project using the push model will export
the repository that developers will push changes to. A project using the
pull model will provide read access to everybody; developers create branches
of the repository and pull changes into the main repository from their
personal branches. The slide model allows for both development methods.
.NH 2
Creating a repository
.LP
The first step any project must take is creating a repository, either empty
or initialized from a certain set of sources. One interesting aspect of vcs
is that the creation and branching of a repository are essentially the same
operation. Repository creation can thus be done in one of several manners.
.IP \(bu
Initialize a new repository without importing sources.
.P1
srv% vcs/newrepo myproject
Enter description of project:
[Description of project typed in stdin]
^D
.P2
.IP \(bu
Initialize a new repository and import sources (this is no different than
the previous command; it simply illustrates the possibility of an import at
creation time).
.P1
srv% vcs/newrepo myproject import project_1 project_docs
Enter description of project:
[Description of project typed in stdin]
^D
.P2
.IP \(bu
Create a new branch of a repository.
.P1
srv% vcs/slide myproject into local_workspace
Branch local_workspace does not exist, create a new repository (y/n)? y
Enter description of branch:
[Description of branch typed in stdin]
^D
.P2
.LP
As is apparent, there is no inherent difference between a branch and a
repository within vcs. Thus, when creating a branch, you retain the history
of all branched files. These files are also given a new revision marking
the branch with a log containing the branch description. You might wonder
what happens if the branch ``repo_name'' already exists -- this will be
discussed shortly.
.NH 3
Configuring repository behavior
.LP
To provide flexibility, it is possible to configure the (as yet) only
option per-repository, which reflects the repository development model.
When unset, the option implies running under the slide model (hybrid
mode). A vcs repository can be configured to operate under push and
pull modes. For example:
.P1
srv% vcs/configure myproject push_only
Repository myproject configured as a centralized ("push model") server.
srv% vcs/configure myproject pull_only
Repository myproject configured as a distributed ("pull model") server.
srv% vcs/configure myproject hybrid
Repository myproject operating in default hybrid ("slide") mode.
.P2
.LP
When operating in different modes, vcs provides features specific to
the model it is serving.
.IP \(bu
When operating in push mode, edits are registered with the server. It is
thus possible to tell who is editing what files.
.IP \(bu
When operating in pull mode, a notification model is available that
allows remote repositories to notify others of changes and submit
patches. For users familiar with Plan 9, this functionality is similar
to that of the
.CW patch (1)
utility. This is achieved by holding a separate repository containing
notifications and their corresponding patches.
.IP \(bu
The default operation allows for both of these features, incorporating
both modes of operation.
.NH 2
Manipulating files in an existing repository
.LP
Most of the time spent on a project is in the development and planning
stages; making changes to a repository should neither be time
consuming nor difficult. Depending on the server model, changing files
and incorporating patches is done in different ways. Since vcs
operates in hybrid mode by default, examples of modification in both
push and pull modes will be demonstrated in a hybrid repository.
These examples can also be used when operating in either of the
non-hybrid modes.
.NH 3
Editing files
.LP
Depending on the development model being used for a project, editing
files will happen in a different way reflecting the mindset behind
that model. Developers used to worked under a push model would be
surprised to know that modifications under a pull model are done
directly in the local branch. This is not possible when developing in
a push model*.
.FS
*While one could feasably edit the files directly in the repository,
it is not recommended and measures are taken to ensure that these
files are not edited. Modifying these files by hand could break the
repository.
.FE
When working under a push model, files are marked as being edited
before they are opened for editing, as illustrated below.
.P1
srv% cd myproject/.workspace
srv% vcs/edit main.c
Opening myproject/main.c for edit.
srv% vcs/edit doc/README
Opening myproject/doc/README for edit.
srv% vcs/edit doc/NOTES
Warning: myproject/doc/NOTES is also being edited by user fred
Opening myproject/doc/NOTES for edit.
.P2
In the final case, it is apparent that the file is being edited by
another user. In such a circumstance, both users are allowed to edit
the file on a first-finished basis. The first developer to finish
editing and pushing the file into the repository will win, no matter
who opened the file first. In such a situation, the latter developer
will either have to merge changes or arrange that with the other
developer. Submitting the changes in the workspace is discussed
following the next section.
.LP
Because the development mindset of the push model differs radically
from that of the pull model, the above functionality is missing when
working under the pull model. Under this model, files in the local
workspace are directly modified. That is to say, work is done within
the .workspace directory of the local branch:
.P1
srv% cd myproject/.workspace
srv% acme main.c
.P2
No notification that files are being edited is necessary (every
developer should have his or her own local branch; no protection is
needed against multiple developers working on the same file).
.NH 3
Developing under the pull method
.LP
If you are not working in a hybrid or pull repository, you can safely
skip this section.
.LP
Creating a local branch of the repository is the first step to
working in the repository. As shown above, this process happens as
follows:
.P1
srv% vcs/slide myproject into local_workspace
Branch local_workspace does not exist, create a new repository (y/n)? y
Enter description of branch:
Local working branch for development of project myproject.
^D
.P2
.LP
After changes have been made to the necessary files, there are two
ways to merge these files back into the head repository. The first
method is the notify / pull method. In this case, a notification is
sent to the main repository containing a description of the changes,
as well as a set of incremental patches containing the history of
the changes in the local workspace.
.P1
srv% vcs/notify myproject from local_workspace
Enter name of notification: spelling_warning_fix
Enter description of changes made:
Fixed spelling errors in documents and fixed compiler warnings in
C code.
^D
.P2
.LP
After submitting the notification, the changes must still be merged
into the repository. This can be done as follows:
.P1
srv% vcs/notifications myproject
spelling_warning_fix: Fixed spelling errors in documents and ...
some_other_fix: Add documentation for frob Q and grob S.
srv% vcs/slide myproject.notify.spelling_warning_fix into myproject
Merging notification "spelling_warning_fix" into repo_name
srv%
.P2
.LP
The other method is to pull the changes from the local workspace
into the main repository. This example illustrates what happens when
sliding into an existing branch.
.P1
srv% vcs/slide myproject.local_workspace into myproject
Merge changes from local_workspace into myproject (y/n)? y
Enter description of changes made:
Importing changes from local branch local_workspace.
^D
.P2
.LP
As with merging patches from the notification branch into the main
tree, the patches are applied incrementally, giving a full history of
the files as they were edited in the developers' local workspace.
.LP
Since the mindset behind distributed project development with the pull
method encourages that patches not be submitted nor imported before
they are tested and working and because there may be multiple milestones
between the beginning of an initiative and submitting it via notify,
it is possible to mark milestones in the development with the snapshot
command, as illustrated below:
.P1
srv% vcs/snapshot local_workspace
Enter milestone:
Stage 2 / 5: added several new menu types. Still buggy; this will
be fixed in stage 3.
^D
.P2
.NH 3
Developing under the push method.
.LP
As illustrated above, files are modified in the repository's
workspace. When changes have been made, these can be committed to the
main repository as outlined below:
.P1
srv% vcs/slide myproject.workspace into myproject
Enter description of changes:
Updated documents..
^D
.P2
This process will go through the database of files marked as edit by the
submitting user and merge them into the repository.
.NH 3
Hybrid development
.LP
Development in a hybrid environment provides the advantages of both
methods, but does have some differences when working under the push
method. Namely, remote developers need to have some sort of guarantee
that
.NH 2
Subscribing to notifications
.LP
In a distributed environment, users should be able to tell when
changes are made to a project. Failing to provide this feature means that
projects with distributed developers will need to spend much more time
communicating logistics than developing. Thus, vcs provides a notification
subscription system so that developers can be kept up to date as to what
is going on with remote projects without needing access to the repositories
themselves.
.NH 3
Setting up subscriptions
.NH 3
Remote to local
.NH 3
Local to remote
..
|