Copyright © 1998 by Brad Appleton, Stephen Berczuk,
Ralph Cabrera, and Robert Orenstein.
Permission is granted to copy for the PLoP '98 conference.
The following is a brief introduction to the concepts of file
checkin/checkout, and to branching and merging. If you are already
familiar with these concepts you may safely skip this section.
Most version control tools in widespread use employ the
checkout-edit-checkin model to manage the evolution of
version-controlled files in a repository or codebase.
Developer's checkout a file from the codebase into their workspace
where they perform and then test their modifications. When they are
finished, they checkin their modified source file revisions back into
the codebase. No files may be modified unless they are first checked-out.
In a strictly sequential development model, when a developer checks-out
a file, the file is write-locked: No one may checkout the file if
another developer has it checked-out. Instead, they must wait for the
file to be checked-in (which releases or removes the write-lock). This
is considered a pessimistic concurrency scheme which forces all work to
take place on a single line of development.
Branching is a common mechanism used by many version
control (VC) tools to support concurrent software development.
In its most basic form, branching allows development to take place
along more than one path for a particular file or directory. If one
developer wants to checkout a file that another developer has already
checked-out, she merely creates a branch and then checks-out the
file on the new branch. This is an optimistic concurrency scheme that
creates a parallel line of development for the file.
Branching can be likened to a Unix fork
that creates a
new thread of execution with copy-on-write semantics. When a branch is
created, the contents of the revision serving as the branchpoint
are the same as the contents of the initial revision on the newly created
branch. When the revision on the new branch is modified and checked-in,
the two lines of development will have different contents and will
evolve separately, in isolation from one another.
Merging is the means by which one development line
synchronizes its contents with another development line. When merging
from a child branch back to a parent branch, the contents of the latest
version on the child branch are reconciled against the contents of the
latest version on the parent branch (preferably using a 2-way or 3-way
file differencing or comparison tool). The contents of the two files are
merged together into a new revision which must correctly resolve any
conflicting changes made along each development line since the
branchpoint was created (or since the last time the two development
lines were synchronized).
So far we have discussed checkout/checkin (and branching) of files and
directories. Files and directories are physical configuration
elements for software. Most VC tools that support branching let
you checkout/checkin files, and perhaps directories. Some VC tools are
integrated with programming environments and let you checkout/checkin
logical configuration elements, typically programming language
elements like classes and methods (or modules and functions).
The discussion throughout Streamed Lines assumes that files
and directories are the minimal configuration elements, but the ideas
and strategies presented here are applicable to VC tools that allow
branching of methods and classes. They also apply equally well to most
any kind of software artifact (not just source-code files).
[back to the table of contents]
Send us your comments!