AccuRev’s Stream Hierarchy

This section discusses the AccuRev implementation of software configurations.

Be sure to read What is a Software Configuration? before starting this section. First, we set the scene and introduce some necessary terminology.

AccuRev’s basic job is to keep track of the changes that a development team makes to a set of files. That’s called version control. A file under version control is called an element; developers can create any number of versions of each element. AccuRev saves all the versions permanently in a depot.

Note: We are oversimplifying here. AccuRev version-controls directories as well as files; and there can be multiple depots, each one storing a separate directory tree. But the above paragraph is enough to get us into a discussion of software configurations. For more on depots and version-controlled files and directories, see section The AccuRev Data Repository.

AccuRev can manage any number of configurations of a depot’s elements. Each configuration contains one version of every element in the depot — or perhaps, just some of the elements. Here are the basic data structures:

  • A stream is a configuration of the depot that changes over time.
  • A snapshot is a configuration of the depot that never changes.
  • A depot’s streams and snapshots are organized into a stream hierarchy: each stream or snapshot has one “parent”, and can have any number of “children”.

The stream hierarchy can be changed at any time: move a child to a different parent, interpose a new stream between a child and its parent, etc. Using these structures, it’s easy and intuitive to model many aspects of the software development process.

The main idea is to enable multiple development tasks to take place concurrently, and to manage when (and if) work done for one task is shared with other tasks. For example:

  • A stream corresponds to a development task. It might be a long-lived project, such as “the Release 2.5 development effort”; or it might be a quickie, such as “fix error message ERR037”. When a developer modifies an element, the new version is recorded as a change to the configuration of a particular stream.

  • A snapshot corresponds to a project milestone, such as “Build 451” or “Release 2.5 final build”. It’s vitally important to be able to tell exactly which versions of which files went into Build 451, no matter what changes were made subsequently. A snapshot answers this need precisely and completely reliably, because it’s a never-changing configuration.

  • A “parent” snapshot acts as a stable starting point for any number of “child” streams. No matter when a new child is created, its initial configuration is an exact copy of the parent snapshot. This structure is appropriate for managing multiple bug fixes to an old release. Each bugfix stream starts with the versions that were used to build the original release — say, the versions in snapshot “Release 2.5 final build”.

  • Versions created at the bottom of the stream hierarchy rise up through the hierarchy by being promoted from stream to stream — from child to parent, then from parent to grandparent, etc. Promotion is one of AccuRev’s most important operations, enabling you to intuitively model a project’s workflow.

    For example, after initial development work on a set of files is completed, the files are submitted to unit testing, then to internal system testing, then to external system (“beta”) testing, then to final production. If this workflow is too elaborate for your organization, or not elaborate enough, just design your stream hierarchy differently. You can redesign a project’s workflow at any time by changing the stream hierarchy.

  • A parent stream provides an integration point for any number of child streams. This structure is appropriate for a development effort that is divided into multiple tasks, to be undertaken concurrently by different developers. As developers complete their changes, they promote the changes to the parent “integration stream”.

    If two or more developers happen to change the same file, AccuRev detects the version conflict and assists the developer with a merge. This ensures that one person’s work is not overwritten accidentally by another person’s.

    Note: The merge conflict is detected when the second developer attempts to promote the element. The versions must be merged before AccuRev will permit the second promote to succeed.

    • Each stream provides a change scope for the subhierarchy beneath it: child streams, grandchild streams, etc. Once a version has been promoted to a stream, that version becomes available to the stream’s entire subhierarchy. In many cases, the newly promoted version will appear automatically in (“be inherited by”) all the descendant streams.

      For example, suppose a new corporate logo has been designed and saved in a new version of file corp_logo.png. Promoting this version to a high-level stream makes it appear instantly in many lower-level streams where Web pages are being developed and update.

    • Occasionally, you may want to stop sharing changes and to back out a specific version of an element so that the version is no longer available in that stream. In such cases, you can either abandon any changes made to a file by reverting the file to the state it was in when it was last “backed,” or you can remove the changes from a parent stream while retaining those changes in a child stream by demoting the file.

      Performing a revert-to-basis procedure on a file rolls back a workspace to using the file version that it contained the last time the file's status was (backed). Any content or namespace changes you have made to the file since then are abandoned. The file remains active in the workspace.

      Unlike a revert process, a demote operation does not abandon your changes. Instead, the changes become active in a child stream or workspace you specify. A demote operation is conceptually the opposite of a promote. That is, a promote operation shares your changes with other users while a demote stops sharing changes. The main use of a demote operation is to back out changes, such as those associated with defects, from a given parent stream so that they are no longer visible there while, at the same time, making those changes available in a child stream or workspace where those versions are now active.

      You can demote by transaction, issue, or file. When you demote by transaction, the specific versions of the files in that transaction are moved from the parent stream to the child stream you specify. If you demote by issue, you move the changes associated with that issue from the parent stream to the child stream. When you demote by file, the demoted file is removed from the default group of active files in the parent stream and added to the default group of active files in the child stream.

      It may be worthwhile to study the above scenarios a bit more, and to consider how your organization might use AccuRev’s streams and snapshots in your own development environment. As you do so, keep these two important points in mind:

      • A stream is a software configuration, a specification of particular versions of particular elements. A stream doesn’t contain copies of files stored in the depot’s file storage area; it just contains a “set of versions”, selected from all the versions recorded in the metadata stored for the depot.
      • A depot’s files are organized into a directory tree; a depot’s streams are organized into a tree-structured hierarchy. These two tree structures are different and independent of each other. In a sense, the directory tree is a “picture” of the file system representation of the elements, and the stream hierarchy is a “picture” of the software development process that creates and maintains the elements.

    See also: