Best Practices, Traps, and Pitfalls
by Brad Appleton
Introduction
This page attempts to catalog common practices with the ClearCase
software configuration management tool. At present, no attempt is made
to distinguish which practices are "good"and which ones aren't.
At a later date, I hope to be able to sort the common usage patterns
listed here into "best practices"and "traps and pitfalls."
I hope to determine this by having people from various development shops
answer the following questions for each practice that they actually use:
-
Do they consider it a "best-practice"?
Why or why not? (what is the rationale)
-
What is the underlying problem the practice solves for them?
-
What are the benefits they see resulting from its use?
-
What are the drawbacks (tradeoffs) they see?
How are they handled?
-
What circumstances make this a "best-practice" for them that
might make the practice inappropriate under different project conditions?
-
What were the motivating factors that made this alternative more
attractive than others that might have been considered?
-
What related practices do they use that depend upon
(or are depended upon by) this one?
Currently, the practices are partitioned into the following
areas (with some overlap):
Early Branching is when codelines for new development or
integration are created right away, as soon as any work on the
corresponding project or release begins. This is often used when
the mainline is a "Stable Receiving Line" reserved only for merges
of baselines. New codelines are spawned off the mainline as soon
as the corresponding work begins.
For example, if work on release 1.0 has completed and work
on 1.1 is taking place, and at the same time, work on release 2.0
is about to start, then a new codeline is branched off mainline
for work on release 2.0 at that point (and if it isn't already,
work on release 1.1 and other version 1 maintenance releases) goes
on its own branch.
Thus Early Branching merges into mainline with the old baseline,
and then branches out from mainline for the new development/release.
In contrast to "Early Branching", Deferred Branching
(also called Lazy Branching) is when branch creation
for new development/integration codelines is put off until the
last minute. This is often used when the mainline is a "Latest
and Greatest Development Line" (or "LAG Line"). The latest and greatest
development work takes place on the mainline, or the main development
line (which might not be /main), and codelines are branched off
only when the corresponding work is no longer the latest
and greatest.
For example, when working on release 1.0, development happens
on the mainline. Work on 1.1 and 1.2 (and 1.x) also happens on the
mainline until work on the next release (2.0) starts to take
place in parallel. At that point, development for release 2.0 takes over
the mainline, and then a separate branch is created for maintenance
work on release 1.x.
Thus, instead of branching for a new release-line as soon as work begins
on the release, we wait to branch it off mainline, until it goes into
maintenance mode or until development on a subsequent release begins
in parallel from existing work. At which time its out with the old
(it gets a new codeline branched out from main) and in with the new
(the new development work comes in on the mainline).
The reasoning here is that by branching later rather than earlier, there
is a single codeline for a longer period of time and changes simply get
merged into the single codeline instead of having to get merged into
two parallel codelines. Once the second codeline is split off from the
first (regardless of early or late creation), then changes made in the
newly branched codeline often need to be propagated back to the parent
codeline somehow (either my merging the changes themselves, or by merging
the codeline to its parent to "synch-up"). This is a trade-off of safety
in favor of liveness (productivity): by waiting longer before splitting
off a new codeline, the amount of propagation and synch-ing effort is
reduced, at the risk of having less separation/isolation of change.
Some shops avoid branching directories in ClearCase because when
directories are created on a branch, or their contents are altered
on a branch (a file is added or removed to its list of elements),
they sometimes run into problems with visibility of elements,
often resulting in the same element being created twice on different
branches.
Other shops use branches for directories in the same way they would
for any other elements. And if they have a reasonably organized
and disciplined and consistent use of branching, and are sure to
integrate early and often, they tend not to suffer too much from the
aforementioned problems.
Many groups use specific naming conventions for the various kinds of
branches that are created. There will typically be some portion of the
name that indicates the type of branch (release-line, component-line,
integration-line, fix/feature). If the branch corresponds to a major or
minor release, then the release number is usually included. If it
corresponds to a record in a tracking database, the database-ID of the
record is often part of the branch name as well. Some may also employ the
primary developer's username as part of the branch-name.
Use of a prefix to indicate the type/purpose of a branch (e.g., "rel", "int",
"fix", "feat", "dev", "tst", "comp", "prod", "proj", etc.)
Use of the major and/or minor release version in a branch name
(e.g., "rel1", "rel1.2", "rel2.X").
Use of change requests tracking systems corresponding request ID
as all or part of the branch name (e.g., "cr123", "bug243", "feat331").
Use of sole or primary developer's username as all or part of the
branch name (e.g., "calvin", "hobbes_bug243", "suzy_feat331").
Use of a component-name or subsystem-name as all or part of the branch
name (e.g., "GUI_rel2.6", "MMI", "ACG-1234").
Use of an indentifier corresponding to the purpose of the task as all or
part of the branch name (e.g., "flush_on_write", "fix1234_confirm-exit").
A Task Branch is a branch that is used only for development of
a single task. When the task is completed and the changes have been
tested in isolation, then the change-task branch is merged into the
integration branch (usually its parent). After the change-task is
completed or integrated, its not uncommon for it to be "locked down"
(retired) from any future changes.
If all change-tasks must be performed on their own task-branch,
this is called the Branch per Task approach. Some groups
instead prefer to use a Branch per Major Task creating task
branches only for more involved (higher risk or longer-lived) efforts,
and performing short and (seemingly) simple tasks "on-line" (directly on
the codeline instead of on a separate task-branch).
A Fix Branch is a task branch created for the purpose of
fixing a "bug" in the software.
This is basically the same thing as "Branch per Task". The main difference
is that in this case, branches are only created for formal requests logged in
a bugtracking and/or change-request tracking database, and other untracked
change-tasks might or might not have their own task-branch.
One of the more common uses of codelines is to house development work
for a specific major or minor release (minor releases are sometimes
called "point releases" because they only affect the number
after the first "point" in the version name/number). Some groups
also use branches to shore up work in major or minor system features,
(possibly independent of which release-line they may end up getting
merged to).
It's common for a group to use task-branches for enhancements
and bugfixes that stem from change-requests and/or bug-reports.
Its less common to see this same philosphy applied to initial
feature development as well (before an initial baseline
is created), or before a codeline goes from pure development mode
maintenance (and development) mode.
With feature branches, "feature" tasks are created in the tracking system
that correspond to new development features to implement in the next or
current release. Some of these features may encompass more than a single
discrete development task, but often they will correspond to a single task.
(In the case of the former, the feature branch may turn out to be a special
kind of subproject line called a "feature line" - feature lines typically
are smaller units of functionality than "functional lines").
A "private" task branch is a task-branch that is specifically locked
right after creation so that only the assigned individual developer
make checkout/checkin any versions on the branch. Sometimes groups
simply use "private branches" by explicit convention, but don't actually
enforce them using ClearCase locks or triggers.
A "shared" task branch is a task-branch that is deliberately planned
and used for development by two or more people on the same branch and
task. This may take place in separate views for each developer, or the
developers might use a shared view (to conserve diskspace and network
reources) if they can obey conventions to prevent each other from
modifying the same sets of files (or at least at the same time).
A Task-Migration branch (or Carry-over branch) is a
change-task branch that is created to propagate a change task from one
"mainline" to another "mainline." When a group is using multiple
mainlines which are long-lived (sometimes each mainline is a different
functional-variant line) then change-tasks made in one mainline often
need to be propagated to one or more other mainlines. Since the context
in which the original change-task occurred may include things that were
specific to its particular variant or configuration, a separate migration
branch is created for each mainline to receive the propagated change. This
keeps the changes isolated on a separate branch of the new mainline so
they can be merged, integrated, and stabilized, before adversely impacting
other users of the mainline.
Its not uncommon for task-migration branches to require a partial
ordering in their integration to a given mainline. Tasks from the same
mainline usually need to be propagated to other mainlines in the same
order they were completed in their initial mainline (unless the tasks
are completely independent and don't share any common context besides a
common baseline).
The Codeline-Owner serves as the integrator and is responsible for
merges all Task-Branches into the codeline. When development is
completed on a task-branch, it has to get merged to the integration
codeline. Sometimes this is done at periodic intervals by a special
"codeline integrator" who is responsible for performing all
integrations into their codeline and maintaining a consistent state.
If done right, it works swell. If done wrong, it can result in a "throw
it over the integration wall" scenario where there is very little
and/or infrequent communication or cooperation between developers and
integrators and working relations between them can become very strained
and unproductive. It also makes it harder for each group to appreciate
the work and needs of the other and they will frequently resist changes
to their own work-habits for the benefit of the other group if they
can't perceive any benefit to their own group.
This is when developers are responsible for merging their own change-tasks
back into the codeline. It is usually done as soon as the individual task
is completed (including after code-review and unit-test).
If done right and with discipline, this too can work out just great.
If done wrong, you can have haphazard changes integrated at irregular
times, and consistency and stability of the codeline can be next to
impossible to rely upon. Regardless of whether developers or separate
integrators merge changes to the codeline, there needs to be a responsible
"codeline owner" who takes to heart the duty of ensuring that changes
are merged in an organized manner and frequency, and that the codeline
is as consistent and stable as possible at all times.
Some shops encourage or require developers to merge the latest state
of the codeline into their task branch and view before allowing
the change to be integrated to the codeline. This ensures that the
merge to the codeline will always be a trivial one (provided its
performed very shortly thereafter or else in a controlled order)
regardless of whether the merge to the codeline is performed by the
developer or an integrator.
The downside of this is decreased separability of the change-task from
its initial baseline/context. If any merges were made to files on the
task-branch, then the branch now contains (and may depend upon) more
changes than just the task plus the baseline it was first branched off
from. Backing out such changes can be harder to locate or disentangle
unless other measures are taken (like checkpointing the versions on the
branch before syncing-up with the codeline). The likelihood of merge
problems to be handled by an integrator is often decreased because
changes are merged by the developers who made them, and codeline
integration is usually trivial. But when a problem does occur, its
likely to be more of a hassle to resolve.
The main issue has to do with whether the particular environment makes
developers more or less likely to be as familiar with the latest state
of the codeline as they are with their own changes. If they are, then
the developer is typically best suited to do the merging; otherwise the
codeline-owner is usually the better choice (and sometimes you need
both :-)
An Integration Line is a branch that is used primarily, or even
exclusively for performing integrations of incoming changes.
Some like to make the distinction between an "integration line"
versus an "integration "branch" (or "integration-task branch"). They use
the term Integration Line to refer to a codeline that is created
in advance, ahead of many of the changes that will be integrated. When a
change is made on its own task-branch, after the change is debugged and
tested, it then gets merged into the already created integration line.
So the integration-line lives on after the merged task-branch is completed
and remains active to in order to merge many other task-branches as they
start and finish during the lifetime of the integration-line.
In contrast to an Integration Line, an Integration-Task
Branch typically doesn't get created until after most
of the development changes to integrate have already begun, and
often isn't created until most of the development changes are ready
to be merged. The "integration-task branch" is then created (and
sometimes the codeline is frozen from further development changes
until the integration is completed). The integrator then merges in
each of the ready-to-be-merged development changes in rapid succession
(hopefully in some intelligent order based on change-dependencies). So
the lifetime of an integration-task branch usually doesnt span over
multiple task-branches; it typically doesnt start until most of the
task-branches are well underway and ready for integration.
Some groups allow developers to checkout/checkin on the integration line.
It may be that all development happens on the integration line until an
initial baseline is created and/or the codeline goes into "maintenance
mode." Or else developers perform minor change-tasks "online"
using task-branches only for what they consider "major" changes.
Some groups forbid development tasks on the integration-line, reserving
it only for integration of task-branches (which might be performed by
an integrator, or by the developer).
This is a codeline created to house platform-specific work of
the system. It might be for a different operating system, or
different hardware, or a different windowing environment. But
code specific to the particular operating environment has its
own platform-speficic integration line.
The more commonly recommended way to handle this is to use platform
specific subdirectories and files. Rather than use a sea of #ifdefs
to create conditionally compiled spaghetti code, platform-specific
code is split out into separate compilation units in a subdirectory
named after that platform (or the platform might be a prefix in the
filenames). Then a variable can be used in the Makefile(s) to select
the specific platform files and directories.
Platform-directories are usually preferred over platform-branches,
but occasionally one runs into cases where platform-branches really
do seem to make sense.
If the product being constructed has several different functional
variants that need to be built, then either each functional variant is
given its own codeline; or else each major function that may be varied
is given its own codeline and then the versions from the appropriate
mix of functional lines is configured to form the desired functional
variant of the product.
Sometimes the system is partitioned up into an explicit list of
component or subsystems. And a separate team is often assigned to work
on each component. It's not uncommon for each component team to create
its own component development barnch as the main integration branch for
the component, and then development for the component takes place on
the component line, or else on one of its sub-branches and is
eventually integrated to the component line.
Baselined versions of each of the various components are usually
integrated together to configure a complete system build. Sometimes
this is done by having each component line merge its latest state into
a system-wide integration line, sometimes it's done simply by
integrating in the LATEST versions on each components, and sometimes
its done simply by selecting the appropriate baseline label for each
component in the config-spec (there is rarely ever any overlap between
the sets of files making up a given component).
The difference between a "component line" and a "functional line" is
that a functional line is for a variant piece of functionality that is
not always part of every released configuration. Whereas a "component"
line is reserved for work on a particular subsystem regardless of
whether or not it is always released with every configuration.
A project line may be thought of as virtually any branch or codeline
created for one or more related tasks with a common goal. A
release-line (the main development or integration line for a specific
release) can be thought as a project line whose goal is to deliver a
particular release.
It is extremely common for groups to have a main integration line for
their work on a particular release (or project), and for all other work
to take place other directly on the release-line, or else on a single
branch off the release-line for a single task (a bugfix or enhancement)
which then gets merged into the main integration line upon completion.
A Subproject Line is a codeline branched off the main
integration line that is used for work which spans more than one
development task (and hence more than one "task-branch"). Sometimes two
or three people work on interdependent tasks on their own separate
branches. Rather than each referring directly to the others branch in
their configurations, the create a common subproject integration line
for their work, and refer to the subproject line instead of someone
else's task branch. When someone needs the latest state of someone
else's branch, they ask that person to merge to the subproject branch.
When all the interdependent tasks are finished and integrated to the
subproject branch, then the subproject branch is ready to be merged
back to the main integration line.
So a common indicator of a subproject line is when branches are more
than one level deep off the main integration line for the release or
project codeline. It helps avoid the scenario of "spaghetti branching"
where individual task branches explicitly depend on other task branches
in a haphazard fashion, much like the haphazard use of unstructured
gotos in a program leads to spaghetti code.
When source-code (or other kinds of files) are supplied by some external
third-party vendor or supplier and require local modifications they need
to be version controlled. The problem is that this needs to be done in
a way that minimizes integration effort when obtaining a new release of
files from the supplier while accommodating local changes that had to be
made.
The common approach to this problem is to use a Third-Party
Line or Vendor Branch. Rather than trying to maintain
both the vendor-supplied versions and the locally modified versions on
the same codeline, a separate codeline is used to hold only the vendor
supplied releases of the files. The first time the files are received,
the vendor line is created separate from the local development branch
(which one branches off of which isn't a big deal, it can happen either
way). Then local changes are made on the local development line. When a
new release is received, it is checked-in to the vendor-line, and then
merged (integrated) into the local development line.
Sometimes various "promotion levels" are defined along with the linear
progression from one promotion level to the next. The criteria used to
decide what constitutes a "promotion level" and when to promote something
to the next level may vary widely depending on how the group chooses to
define them. These promotion levels may correspond to levels of testing
or SQA (e.g., inspected, unit-tested, intg-tested, sys-tested, ...), or
to levels of scope/scale (unit, component, subsystem, system, ...), or
to levels of authority/responsibility.
One way of using promotion levels is to use a separate integration
line per promotion level for each release or each mainline. When
a version is merged from one promotion branch to its successor, it
has been "promoted" to the new level.
Staged Lines is when there is a promotion branch for each promotion
level. Codeline Promotion (or Branch Promotion) is
when the branches get promoted, rather than the versions. Instead of
having a branch-per-level, a single codeline has a "level" or state
associated with it that indicates the current promotion level of all
versions on that branch-type. (One typically uses an attribute on the
brtype to indicate the promotion level, and hyperlinks might even be
used to indicate predecessor and successor levels). When the versions
on a codeline are deemed stable and ready to proceed to the next level,
the level is associated with the branch, and the branch itself is what
gets promoted (instead of copymerging all the versions to another branch).
This deals with propagating changes from other integration branches.
If a change is made in one codeline that is needed in another codeline
(for example, a bugfix in release 1.0 might happen on the release 1.1
codeline, and the fix also needs to find its way into the release 2.0
codeline), some groups simply wait for some (possibly long) durations
before merging those changes from one codeline to the other.
Other groups however will propagate changes early and often,
syncing up the changes in one codeline (e.g. the rel-1.1 codeline) with
the other codeline (e.g. the rel-2.0 codeline) at regular and frequent
intervals (sometimes per-task, other times daily, or weekly).
A Release Branch is a codeline reserved for work towards
a particular release or a major release.
Usually the release codeline is a kind of integration branch.
Sometimes a Release Codeline will have its own separate integration
branch, but that is relatively rare.
A major release codeline is one that would be created for all
releases with the same major version number (e.g. 1.0, 1.1, ..., 1.x).
So a release 1.x codeline would be used for integration (and/or
development) of all features for release 1 and all its subsequent
maintenance releases and patches. If early branching was used, the
major release line is created right away. Otherwise if lazy (deferred)
branching was used, it might not be created until just before or just
after the initial major release of that code (in which case most of the
development happened on a LAG mainline, and the branch was created for
release engineering and integration as well as for subsequent maintenance).
This is when a release branch is created for every release (major and
minor). More often than not, each release-line is branched off from the
mainline (possibly after syncing up the mainline with other release
lines first, to "refresh" it with the latest baselines before branching
off of it - this helps avoid continually cascading release lines off
release lines).
Sometimes a release-line is branched off the major release line for
each specific release (instead of from the mainline). In this case the
Major release-line may serve as either a "Stable Receiving Line" if
Early Branching is used, or a "LAG development line" if Deferred
Branching is used.
Sometimes major-release lines are always created, and branches are only
created for a specific release of the major-release in the event they
seem absolutely necessary for a bigger/tougher than usual release
engineering effort (in which case they are often quickly merged back to
the major release-line when finished).
In addition to branching for major or minor releases, sometimes a
separate branch is created for a specific patch-effort. The effort
might simply be for a single task that results in a released "patch",
or it might be more long-lived over several tasks (usually for a
limited period of time, like a month or two) and results in a released
patch (possibly before or after merging it back to the release-line).
The more common case is where code on the patch-line is released only
after everything on the patch-line has been integrated and baselined.
However some groups that need to very quickly respond to a set of internal
or "in house" users will use the patch-branch (and its corresponding
workspace) as a kind of emergency patch-release area to quickly push
out incremental fixes to a recent release.
A mainline is kind of a "homing line" or "anchor" for all other paths
of development branched off from it. If there is only one persistent
variant of the code (e.g. no platform-lines nor functional-lines are
needed) then only one mainline is usually required. (And in
ClearCase this will almost always be "/main".)
Mainlines are typically used primarily for integration, and serve as a
stable receiving line; or else they are used as the primary LAG development
line. Some groups even use a LAG development mainline that
gets periodically merged to an integration mainline.
Mainlines serve as the main-stream from all other major codelines are
branched. And every major codeline eventually must merge back to the
mainline at periodic intervals and/or before retiring/decommissioning
the major codeline. This helps avoid the "continuing cascade problem"
where each release-line branches of from its predecessor release, and
the predecessor has to propagate its changes to its successor,
resulting in a very deep and wide propagation of changes from
release-line to release-line with no end in sight.
Using a mainline causes all child codelines to regularly merge back to
their common parent codeline, especially before branching a new
codeline off from the mainline. This reduces the breadth of the version
tree, and keeps the level of cascading down to a bare minimum, which
in turn decreases the number of transitive levels of change-propagation
that are necessary.
A Stable Mainline is a mainline that is used solely as
a stable-receiving line to which other stable baselines and codelines
are integrated. Development never takes place on the mainline, and
only stable baselines and/or stable codelines are ever merged to main.
Stable Mainlines are often used in conjunction with
Early Branching.
A LAG Mainline s a mainline that is used for the
latest and greatest (LAG) development of the system or project.
The most recent work for the very latest release/project takes
place on the mainline. Work that is no longer the latest and greatest,
and is not needed in the new latest efforts is branched off into its
own codeline at that time for release-engineering and/or maintenance.
LAG Mainlines are often used in conjunction with
Deferred Branching.
Before branching a new codeline off of the mainline, some shops
will insist that the mainline be "synchronized" (or "refreshed")
by first integrating any outstanding codelines to mainline before
spawning the new codeline's branch.
A select few shops will actually label the baseline before mainlining
the release, and will then move/replace the baseline label after it has
been mainlined (renaming the old baseline label before redefining the
new one).
Some shops employ time-sharing on the mainline. Various teams for the
various releases are working in parallel on their own codeline. When
it comes time for a group to merge their codeline to the mainline,
that group has exclusive ownership of the mainline for the duration of
the integration to main, and no other groups may checkin to the mainline
at that time.
Sometimes this time-sharing takes place before the given codeline is
completely stable or baselined. Intead of (or perhaps in addition to)
merging the latest changes from the mainline into their codeline, they
will merge their changes to the mainline for integration before
baseline and release, and do their build and integration work on the
mainline. This encourages a kind of "hit and run" strategy where
"tiger teams" or "SWAT teams" quickly pounce on the mainline taking it
over, quickly do what they need to do, and then quickly get out.
If there is more than one variant configuration development path
(either for platform-specific development paths, or for functional
variants) then Multiple Mainlines (a.k.a. Alternate Mainlines)
may be used. Each platform-variant or functional-variant is assigned its
own mainline and serves as the "mother of all codelines" within its own
particular variant.
Sometimes when several component-lines are used, the integration-line for
the component or subsystem is viewed as a component-mainline within
the scope of the component. But if there is a system-wide integration line
that all the components eventually merge into, then the system integration
line typically serves as the "mainline" from a whole-systems perspective.
A baseline label that is applied after the corresponding versions have
all been merged back to the "mainline."
A baseline label that is applied after the corresponding versions have
integrated into the "release-line" but before any merges from the
release-line to the mainline.
A label applied to the final set of versions checked-in for a change-task.
A label applied to an intermediate state of the versions in a
change-set or change-package. Subsequent versions may be checked-in before
the change-task is complete, and the checkpoint may be used to recall a
previous configuration of the task if desired.
Like a "task checkpoint" only the versions needed for the
developers configuration are labeled, and not just the working-set of
versions being modified in the view. The config-checkpoint may take a
lot longer to create. It also captures versions of elements that may
have been integrated into the view, but which the developer didn't
modify as part of the change-task.
A baseline label that is created by applying the label to all versions
in the VOB(s) that are selected in the build/integration view's
config-spec. Labeling all the versions in the VOB(s) includes
directory versions (or even Makefile versions) that a config-rec might
(or clearmake) typically miss. It may also label versions that didn't
necessarily participate in the build.
A baseline label based applied to the versions indicated by the
configuration-record(s) (config-recs) of the build.
A Component Baseline is a baseline label created for a component
or subsystem (or some other architectural subset) of the overall system
or product.
A Feature-Set Baseline is a baseline label created for a
cohesively related set of system features or requirements (or some other
functional subset) of the overall product.
A Baselevel or Build-Label is a kind of
internal-use-only baseline. It corresponds to a label that is used to
represent a consistent/stable configuration of the codeline, but which
is not officially delivered or released or otherwise "published"
outside the product development group.
Typically, when a baseline label is created, its definition (the set of
versions it labels) almost never changes once the baseline is "published"
and made available to other users or developers.
A Floating-Label is a label whose definition is periodically
updated. A Floating-Baselevel is a baselevel-label that is
regularly updated to correspond to the most recently integrated stable
state of the codeline. Its not quite as dynamic as .../LATEST, but
its more dynamic than a static label definition that never changes.
Some of the dynamic-update capability of the "LATEST" label is
traded-off to ensure that the resulting labeled configuration is always
a consistent one, but it still tries to be as dynamic as possible within
that constraint.
In contrast to a "floating baselevel", an Incremental Baselevel
does not keep the same name between baselevel definitions. Whenever
the integration and build process creates a stable and consistent
configuration for the codeline, a baselevel-label is created with
some indication that it is the next label in a linear progression
that includes its predecssors and successors (typically by some extra
numeric-field at the end of the label).
It is extremely common to see "floating baselevels" used in
conjunction with incremental baselevels. In this case the floating
label always corresponds to the same set of versions as the most recent
incremental baselevel, and the incremental baselevels record the
sequence and content of stable configurations of the codeline. Sometimes
the floating-label is always a separate label from the latest incremental
label. And sometimes a floating label is renamed to correspond to the
previous baselevel just before the floating label name is applied to
the newest baselevel.
Sometimes various "promotion levels" are defined along with the linear
progression from one promotion level to the next. These promotion
levels may correspond to levels of testing or SQA (e.g., inspected,
unit-tested, intg-tested, sys-tested, ...), or to levels of
scope/scale (unit, component, subsystem, system, ...), or to
levels of authority/responsibility.
One way of using promotion levels is to use a separate label per
promotion level for each release or each mainline. When a version is
is ready to be promoted from one level to the next, the new promotion
label is applied to the version. Sometimes only one promotion-label may
be on a version at a time (per release/mainline) and sometimes a
version keeps all its previous promotion labels when it gets a new one
(like wearing merit badges).
Promotion Labels are when there is a label for each promotion level per
release/mainline. Label Promotion is when the labels get promoted,
rather than the versions. Instead of having a label-per-level, a single
label has a "level" or state associated with it that indicates the
current promotion level of all versions referred to by that label. (One
typically uses an attribute on the lbtype to indicate the promotion
level, and hyperlinks might even be used to indicate predecessor and
successor levels) When the versions on a codeline are deemed stable and
ready to proceed to the next level, the level is associated with the
label, and the label itself is what gets promoted (instead of copymerging
all the versions to another label).
ClearCase configuration records capture and record the set of file
versions that went into a build target, including any derived objects
that were generated and the build script or "recipe" used to generate
each derived object and target.
Some groups use config-recs primarily to serve as a bill of materials
for what went into the build (kind of like a what(1) command is used to
spew out SCCS or RCS versions strings in an object file). This means
that the configuration-record is somehow preserved and checked-in to
ClearCase (will have a baseline label applied to it when a baseline is
created).
Some groups may also use config-recs in the config-spec of a view to
reproduce the configuration of all the versions used as part of a
build. This doesn't always catch the necessary versions of directories
or Makefiles.
Some groups use config-recs but don't necessarily version or label
them. They have config-recs that are referenced by a unique-name for
each build performed in the view (often with the timestamp as part of
the unique-name) and use the config-recs primarily so they can execute
the "diffcr" command to tell the differences between the configurations
of any two builds.
An attribute corresponding to the the ID of a record in a change/defect
tracking system that is applied to a version when it is checked-out.
An attribute corresponding the the ID of a record in a change/defect
tracking system that is applied to a version when it is checked-in.
An attribute corresponding the the ID of a record in a change/defect
tracking system that is applied to a change-task (which may be
represented by a branch or a label).
An attribute indicating the state or promotion level of a version.
An attribute indicating the state or promotion level of a branch.
An attribute indicating the state or promotion level of a label.
An attribute indicating the name/id of the change-set (change-package)
to which this element-version belongs.
An attribute indicating the name of the component or subsystem to which
an element belongs.
An attribute indicating the name of the component or subsystem to which
an element belongs.
A hyperlink from a migration/transfer task (branch or label type)
to the original task being transfered
A hyperlink from a codeline to one or more codelines to propagate changes
to.
A hyperlink from a label or a branch to the predecessor or successor
label or branch that corresponds to the next state or promotion level
in a linear progression.
A hyperlink from a change-task branch/label-type to the baseline
label-type used for its development.
A hyperlink from a change-task branch/label-type to the target
release/baseline label-type that the change is expected to be
integrated and delivered in.
A hyperlink from a change-task branch/label-type to the codeline
branch-type used for its development.
A hyperlink from a change-task branch/label-type, to the target
release/codeline lbtype or brtype that the change is expected to be
integrated into.
A hyperlink from a change-task branch/label-type to one or more
other change-tasks upon which it depends (maybe it merged them in,
or maybe it simply needed to refer to them in its config-spec).
A hyperlink between a branch-type for a codeline, and the label-type
that will be applied once everything has been integrated into that
codeline and the codeline is "retired."
A hyperlink from a codeline branch-type to the branch-type that
serves as it's "mainline."
pre-checkout request-ID validation
pre-checkout element access verification
pre-checkout codeline access verification
pre-checkout comment verification
post-checkout notify
pre-checkin request-ID validation
pre-checkin element access verification
pre-checkin codeline access verification
pre-checkin comment verification
post-checkin notify
pre-unco request-ID validation
pre-unco element access verification
pre-unco codeline access verification
post-unco notification
remove /0 version on unco
remove /0 version and branch on unco .../branch/1 version
remove /0 version and element on unco of /main/1 version
prevent version removal by ordinary users
prevent element entry removal from directories by ordinary users
prevent branch removal by ordinary users
prevent type (lbtype, brtype, etc.) removal by ordinary users
prevent element removal by ordinary users
prevent parallel creation of different files with the same name in the
same directory
modify the protections of newly created elements to give them the
appropriate owner and group and read/write access permissions.
prevent branch-type creation by ordinary users
enforce branch-naming conventions
require comment on branch-creation
attach branch-type attrs/hlinks on creation
prevent label-type creation by ordinary users
enforce label-naming conventions
require comment on label-creation
attach label-type attrs/hlinks on creation
prevent labeling by ordinary users
prevent trigger creation by ordinary users
limit attribute-type creation by ordinary users
limit attribute value assigment by ordinary users
notification of attribute value changes
simulate a pre-op trigger for completion/submission of a change-task
as a single logical change-set.
simulate a post-op trigger for completion/submission of a change-task
as a single logical change-set.
simulate a pre-op trigger for view creation
simulate a post-op trigger for view creation
simulate a pre-op trigger for view removal
simulate a post-op trigger for view removal
simulate pre-op/post-op triggers for entire commands (rather than
individual events)
lock task branch against changes by non-owner
lock task branch/label type against changes after completed submission
lock integration lines against checkin by non-integrators
lock mainline against checkin by ordinary users
lock baseline label definitions after baselining
lock floating labels against change by ordinary users
lock metadata (attributes and hyperlinks) against changes by ordinary
users (unless performed automatically by triggers)
lock elements against modification by unauthorized users
lock "components" or "subsystems" against modification by unauthorized users
lock entire VOBs against access by unauthorized users
View seeding is a way of "pre-populating" a view with the needed
derived object to speedup subsequent builds and winkins.
Some shops have developer's config-specs select the /LATEST versions
on the codeline. As soon as they are checked in to the codeline, the
developers may see them in their views. This can be more problematic
if online development is permitted than if all work is done on
task-branches.
Some shops expressly do not select the /LATEST versions
on the codeline. Instead, the select only the most recently
labeled baselevel of the codeline.
Some shops will use static version selection for files, selecting
the versions on a labeled baselevel, but use dynamic selection for
directories (using a '-directory' rule to select the /LATEST versions
on the codeline for directory elements). This lets developers always see
the latest version of a directory in the codeline, and avoids collisions
resulting from creating files by the same name on different branches. If
a new file has been created by someone else, they will see the new file
in their view, but not necessarily its contents.
Some groups (especially those that dont work directly on /main)
will always insert a rule at the end of a config-spec that
selects the /main/0 version of any file or directory not yet selected.
This lets them see files and directories created in some other branch
so they dont create colliding file or directory elements.
Verify that a particular ClearCase action (e.g., checkin/checkout
or creation of a branch-type or label-type) is performed only by
the user that is assigned or authorized to perform that action as
declared in the corresponding change-request record.
The target-release specified for a record in the tracking system is used
to define or enforce the codeline and/or baseline (branch and/or label)
used for development in the view's config-spec.
Every record for every change-request, bugfix, or
feature/enhancement request is required to estimate
an intended target release for the proposed change.
Some shops require CCB approval before allowing integration
of a requested feature, fix, or enhancement into a release-codeline.
Approval is mode at the level of a given feature or function to decide not
only if it should be integrated, but more importantly which release
codeline/baseline it should be integrated into (possibly changing
previous plans for the targeted baseline/release).
Some shops require CCB approval before allowing integration
of any completed change-task into a release-codeline.
Approval is mode at the level of a given task or subtask to decide not
only if it should be integrated, but more importantly which release
codeline/baseline it should be integrated into (possibly changing
previous plans for the targeted baseline/release).
Subsystems and/or Modules of code are assigned a single owner
responsible for their integrity, and no one but the code-owner is
allowed to checkout (and/or checkin) a piece of code. This actually
applies to other artifacts besides source-code, including documents
and tests.
Subsystems and/or Modules of code are assigned a single owner
responsible for their integrity, and developers other than the code-owner
are permitted to checkout (and/or checkin) a piece of code provided
that they have permission from the code-owner. This actually
applies to other artifacts besides source-code, including documents
and tests.
Individual Codelines are assigned to a single owner responsible for
its integrity and no one but the codeline-owner is
allowed to checkout from (and/or checkin to) the codeline.
Individual Codelines are assigned to a single owner responsible for
its integrity anddevelopers other than the codeline-owner are
permitted to checkout from (and/or checkin to) the codeline
provided that they have permission from the codeline-owner
Some shops require CCB approval for a request feature, fix, or enhancement
before effort has been made to breakdown the proposed work into
tasks and subtasks. Approval is mode at the level of a given feature
or function. Subsequent approval of the constituent tasks needed to
implement the functionality may or may not take place, and rejection
of a task or subtask may change the current accept/reject status of the
corresponding feature or fix.
Many shops require a proposed change to obtain CCB approval before
any development work can begin on that change. This is often done
an a per-task basis, requiring approval for each planned development
task (possibly including subtasks) for a given feature or request.
back to the ACME Home Page