You are on page 1of 5

Common Branching Patterns

Version control is most often used for software development,


so here's a quick peek at two of the most common
branching/merging patterns used by teams of programmers.
If you're not using Subversion for software development, feel
free to skip this section. If you're a software developer using
version control for the first time, pay close attention, as
these patterns are often considered best practices by
experienced folk. These processes aren't specific to
Subversion; they're applicable to any version control system.
Still, it may help to see them described in Subversion terms.

Release Branches

Most software has a typical lifecycle: code, test, release,


repeat. There are two problems with this process. First,
developers need to keep writing new features while quality-
assurance teams take time to test supposedly-stable
versions of the software. New work cannot halt while the
software is tested. Second, the team almost always needs to
support older, released versions of software; if a bug is
discovered in the latest code, it most likely exists in released
versions as well, and customers will want to get that bugfix
without having to wait for a major new release.

Here's where version control can help. The typical procedure


looks like this:

• Developers commit all new work to the trunk. Day-to-


day changes are committed to /trunk: new features,
bugfixes, and so on.
• The trunk is copied to a “release” branch. When the
team thinks the software is ready for release (say, a 1.0
release), then /trunk might be copied to /branches/1.0.
• Teams continue to work in parallel. One team begins
rigorous testing of the release branch, while another
team continues new work (say, for version 2.0) on
/trunk. If bugs are discovered in either location, fixes
are ported back and forth as necessary. At some point,
however, even that process stops. The branch is
“frozen” for final testing right before a release.
• The branch is tagged and released. When testing is
complete, /branches/1.0 is copied to /tags/1.0.0 as a
reference snapshot. The tag is packaged and released
to customers.-
• The branch is maintained over time. While work
continues on /trunk for version 2.0, bugfixes continue to
be ported from /trunk to /branches/1.0. When enough
bugfixes have accumulated, management may decide
to do a 1.0.1 release: /branches/1.0 is copied to
/tags/1.0.1, and the tag is packaged and released.

This entire process repeats as the software matures: when


the 2.0 work is complete, a new 2.0 release branch is
created, tested, tagged, and eventually released. After some
years, the repository ends up with a number of release
branches in “maintenance” mode, and a number of tags
representing final shipped versions.

Feature Branches

A feature branch is the sort of branch that's been the


dominant example in this chapter, the one you've been
working on while Sally continues to work on /trunk. It's a
temporary branch created to work on a complex change
without interfering with the stability of /trunk. Unlike release
branches (which may need to be supported forever), feature
branches are born, used for a while, merged back to the
trunk, then ultimately deleted. They have a finite span of
usefulness.

Again, project policies vary widely concerning exactly when


it's appropriate to create a feature branch. Some projects
never use feature branches at all: commits to /trunk are a
free-for-all. The advantage to this system is that it's simple—
nobody needs to learn about branching or merging. The
disadvantage is that the trunk code is often unstable or
unusable. Other projects use branches to an extreme: no
change is ever committed to the trunk directly. Even the
most trivial changes are created on a short-lived branch,
carefully reviewed and merged to the trunk. Then the branch
is deleted. This system guarantees an exceptionally stable
and usable trunk at all times, but at the cost of tremendous
process overhead.

Most projects take a middle-of-the-road approach. They


commonly insist that /trunk compile and pass regression
tests at all times. A feature branch is only required when a
change requires a large number of destabilizing commits. A
good rule of thumb is to ask this question: if the developer
worked for days in isolation and then committed the large
change all at once (so that /trunk were never destabilized),
would it be too large a change to review? If the answer to
that question is “yes”, then the change should be developed
on a feature branch. As the developer commits incremental
changes to the branch, they can be easily reviewed by
peers.

Finally, there's the issue of how to best keep a feature


branch in “sync” with the trunk as work progresses. As we
mentioned earlier, there's a great risk to working on a
branch for weeks or months; trunk changes may continue to
pour in, to the point where the two lines of development
differ so greatly that it may become a nightmare trying to
merge the branch back to the trunk.

This situation is best avoided by regularly merging trunk


changes to the branch. Make up a policy: once a week,
merge the last week's worth of trunk changes to the branch.
Take care when doing this; the merging needs to be hand-
tracked to avoid the problem of repeated merges (as
described in the section called “Tracking Merges Manually”).
You'll need to write careful log messages detailing exactly
which revision ranges have been merged already (as
demonstrated in the section called “Merging a Whole Branch
to Another”). It may sound intimidating, but it's actually
pretty easy to do.
At some point, you'll be ready to merge the “synchronized”
feature branch back to the trunk. To do this, begin by doing a
final merge of the latest trunk changes to the branch. When
that's done, the latest versions of branch and trunk will be
absolutely identical except for your branch changes. So in
this special case, you would merge by comparing the branch
with the trunk:

$ cd trunk-working-copy

$ svn update

At revision 1910.

$ svn merge
http://svn.example.com/repos/calc/trunk@1910 \

http://svn.example.com/repos/calc/branches/
mybranch@1910

U real.c

U integer.c

A newdirectory

A newdirectory/newfile

By comparing the HEAD revision of the trunk with the HEAD


revision of the branch, you're defining a delta that describes
only the changes you made to the branch; both lines of
development already have all of the trunk changes.

Another way of thinking about this pattern is that your


weekly sync of trunk to branch is analogous to running svn
update in a working copy, while the final merge step is
analogous to running svn commit from a working copy. After
all, what else is a working copy but a very shallow private
branch? It's a branch that's only capable of storing one
change at a time.

You might also like