A baseline is an identified set of files and directories in which there is one and only one version of each file and directory.
A baseline identifies one particular configuration of the software (or a subset thereof)
The baseline represents a fixed point in the development; that may be recreated as required.
Specifying a Baseline
A baseline defines a set of files, each at a particular version. These need not be the latest (most recent) version. A baseline label uniquely identifies the configuration. Files may belong to one or more baselines.
Figure 12 – A baseline defines a set of files, each at a particular version.
In the example of Figure 12 baseline BL1.0 is the first baseline recorded. It consists of seven artefacts, each at a unique revision number. For this example, assume that BL1 records the most recent versions of each artefact. As development progresses each artefact is modified as required (that is, some artefact are modified, some are not). At some time later another baseline is taken – BL2.0. In this case BL2.0 records the current latest revisions of each file. Notice that artefact F is unchanged, so F v1.0 is included in both baseline BL1.0 and BL2.0.
In general each successive baseline contains more recent versions of files (but not always).
When to use baselines
Baselines are a key tool in managing and auditing the state of a project. Baselines should be created prior to any significant project activity:
Baselines provide a ‘working’ point in the project’s configuration. Recording a baseline prior to making a major change to the system allows the development to start from a known working point and, in the event of something going wrong, to ‘roll-back’ to that working configuration.
Baselines should be made prior to starting any new package of work (as evidence of project progress); and new feature development; prior to changing or upgrading any tools; etc.
A baseline records the complete configuration of the product that is being distributed from the development department (whether that is an external customer or just the test department).
Baselines provide process evidence for audits and also time-stamped evidence of the project’s progress (for example, starting a particular work package)
Baseline of baselines
In larger, more complex systems, we may choose to manage the system complexity using a ‘Components’ approach. Each ‘component’ represents some aspect of system functionality – for example a subsystem. Using this approach each component of the system has its own (unique) baselines, independent of any other component (Figure 13).
Figure 13 – each component of the system has its own unique set of baselines
Note, not shown in this example is the fact that components may share artefacts. For example, both component A and component B may share a common artefact H; with each component using a different revision.
Figure 14 – A complete system constructed from a ‘baseline of baselines’
The (complete) product’s baselines are constructed from (unique) combinations of the component’s baselines (Figure 14). This method is known as a ‘Baseline of baselines.’
Branching is the (apparent) duplication of an artefact, or set of artefacts, so that they can be developed independently of the main development activity. Branching is a facility of all revision control systems. RCS systems incorporate mechanisms (such as lazy copying) to avoid the potentially massive overhead of copying artefacts between branches. Branches allow parallel development, which is essential in all but the most simple of software developments.
Conceptually, the artefacts that make up a product or system form the main branch or trunk of the development. The trunk represents the main line of development for the product. Ideally, the trunk represents the most recent (working) configuration of the project. Branches represent alternative paths of development. Motivations for branching include:
- Maintenance of released products
- Customer specific additions or modifications
- New development work
- Research and development projects
Note, with branching the unique identifier of an artefact must be extended to include the artefact’s branch. Thus artefact MyDoc v1.1 will be extended to be (something like) \main\MyDoc v1.0, which will be different to \main\branch1\MyDoc v1.0. In this case \main identifies the trunk branch and \main\branch1 identifies the first branch from the trunk branch.
Uncontrolled branching can lead to major administrative issues (many companies have a RCS administrator simply to keep the repository ‘healthy’)
The branching patterns presented below are a systematic approach to version tree usage. They are design to reduce the complexity of repository branch management and allow effective project management.
The Sequential branching pattern (Figure 15) is the simplest model – in that it contains no branching! In essence, it is a ‘pseudo-branching’ pattern.
All development is performed on the trunk branch. All development is linear; no parallel development can be supported. This pattern requires, and enforces mutually exclusive changes to artefacts. By default, this is the pattern followed by all artefacts.
Figure 15 – The ‘pseudo-branching’ pattern, Sequential. There is no branching!
The Sequential pattern is fine for projects where there is no parallel development required and the current release always has the most up-to-date developments. In general, this restricts the pattern’s use to simpler projects.
The Off-Shoot branching pattern allows a legacy version (the mainline development) to have derivative and independent versions created.
Figure 16 – The off-shoot branching pattern
The off-shoot branch can be created retrospectively – that is, development on the trunk branch could be well advanced before the off-shoot branch is created. The off-shoot is never merged into another branch. Off-shoots may also have their own off-shoots.
Note that the main trunk is baselined before the offshoot is created.
The Loop branch pattern is a variation on the Off-Shoot pattern. The Loop pattern allows basic managed development.
Figure 17 – The Loop branching pattern
In this example the trunk branch represents the release branch. That is, all releases are from the main branch. New development is performed in an Off-Shoot branch (called \Dev BL 2.0 in the example since it represents the new code that will appear in baseline 2.0 of the product). The new development work is independent of any release code.
Once development has been completed in the Off-Shoot branch the Loop is closed by merging the off-shoot back into its parent branch. Note that baselines in the main branch only represent completed development activities.
The Integration pattern extends the Loop pattern model to allow managed and concurrent development.
Figure 18 – the Integration branching pattern
As above, the main trunk branch represents the release branch for the code; no development is performed on the main branch.
For a new feature a new branch is created (\Integration). The new development consists of three work packages. In this example Work Package 1 (\WBS1) must be completed before Work Package 3 (\WBS3) can be started.
Within the \Integration branch two new Loops are started (\WBS1and \WBS2). The work on both packages continues independently and in parallel. When Work Package 1 is complete it is merged into the \Integration branch. At this point Work Package 3 can be started, so a new branch is created from the \Integration branch (after baselining the \Integration branch – not shown). Some time later Work Package 2 is completed and merged into the \Integration branch. Finally Work Package 3 is complete and merged. To complete development the \Integration branch is merged back into the mainline development.
The Integration pattern builds on the smaller patterns to form a comprehensive branch/merge strategy. The strength of this pattern is the RCS archive reflects the development project plan.
- Practice makes perfect, part 3 – Idiomatic kata - February 27, 2020
- Practice makes perfect, part 2– foundation kata - February 13, 2020
- Practice makes perfect, part 1 – Code kata - January 30, 2020
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.
He specialises in C++, UML, software modelling, Systems Engineering and process development.
Nice one Glennan, although I feel like I'm suffering from deja vu 😉
A couple of minor clarifications:
* The sequential branch pattern is the only option for artefacts that do not have a file merging tool. Typically this includes most binary file types such as documentation, drawings, spreadsheets, etc.
* The big difference between the loop and off-shoot patterns is that off-shoots occur retrospectively whereas loops form part of the "planned" development. An off-shoot branch occurs because we have gone back to some earlier point in the version history to make changes.
* Another advantage of the basic loop pattern (and hence the integration pattern) is that the loop is only ever closed (that is merged back into its parent) under the control of the project. This allows the risks in merging to be controlled. It also allows development work to be safely abandoned when business priorities change.