This text is a work in progress—highly subject to
change—and may not accurately describe any released
version of the Apache™ Subversion® software.
Bookmarking or otherwise referring others to this page is
probably not such a smart idea. Please visit
http://www.svnbook.com/
for stable versions of this book.

Vendor Branches

As is especially the case when developing software, the data
that you maintain under version control is often closely related
to, or perhaps dependent upon, someone else's data. Generally,
the needs of your project will dictate that you stay as
up to date as possible with the data provided by that external
entity without sacrificing the stability of your own project.
This scenario plays itself out all the time—anywhere that
the information generated by one group of people has a direct
effect on that which is generated by another group.

For example, software developers might be working on an
application that makes use of a third-party library. Subversion
has just such a relationship with the Apache Portable Runtime (APR)
library (see the section called “The Apache Portable Runtime Library”).
The Subversion source code depends on the APR library for all
its portability needs. In earlier stages of Subversion's
development, the project closely tracked APR's changing API,
always sticking to the “bleeding edge” of the
library's code churn. Now that both APR and Subversion have
matured, Subversion attempts to synchronize with APR's library
API only at well-tested, stable release points.

Now, if your project depends on someone else's information,
you could attempt to synchronize that information with your own
in several ways. Most painfully, you could issue oral or
written instructions to all the contributors of your project,
telling them to make sure they have the specific versions of
that third-party information that your project needs. If the
third-party information is maintained in a Subversion
repository, you could also use Subversion's externals
definitions to effectively “pin down” specific
versions of that information to some location in your own
working copy (see the section called “Externals Definitions”).

But sometimes you want to maintain custom modifications to
third-party code in your own version control system. Returning
to the software development example, programmers might need to
make modifications to that third-party library for their own
purposes. These modifications might include new functionality
or bug fixes, maintained internally only until they become part
of an official release of the third-party library. Or the
changes might never be relayed back to the library maintainers,
existing solely as custom tweaks to make the library further
suit the needs of the software developers.

Now you face an interesting situation. Your project could
house its custom modifications to the third-party data in some
disjointed fashion, such as using patch files or full-fledged
alternative versions of files and directories. But these quickly
become maintenance headaches, requiring some mechanism by which
to apply your custom changes to the third-party code and
necessitating regeneration of those changes with each successive
version of the third-party code that you track.

The solution to this problem is to
use vendor branches. A vendor branch is
a directory tree in your own version control system that
contains information provided by a third-party entity, or
vendor. Each version of the vendor's data that you decide to
absorb into your project is called a vendor
drop.

Vendor branches provide two benefits. First, by storing the
currently supported vendor drop in your own version control
system, you ensure that the members of your project never need
to question whether they have the right version of the vendor's
data. They simply receive that correct version as part of their
regular working copy updates. Second, because the data lives in
your own Subversion repository, you can store your custom
changes to it in-place—you have no more need of an
automated (or worse, manual) method for swapping in your
customizations.

Unfortunately, there is no single best way to manage vendor
branches in Subversion. The flexibility of the system offers
several different approaches, each of which has its advantages
and disadvantages, and none of which can be clearly considered
a “silver bullet” for the problem. We'll cover a
few of these approaches at a high level in the following
sections, using the common example of a software project which
depends on a third-party library.

General Vendor Branch Management Procedure

Maintaining customizations to a third-party library
involves three data sources: the version of the third-party
library upon which your modifications were last based, the
customized version (that is, the actual vendor branch) of that
library which is used by your project, and any new version of
the vendor's library to which you may be hoping to upgrade.
Managing the vendor branch (which should live within your
source code repository per our definition of the thing), then,
essentially boils down to performing merge operations (in the
general sense). But different teams take different approaches
to the other data sources—the pristine versions of the
third-party library code. Thus, there are likewise different
specific ways to perform the requisite merges.

Strictly speaking, there are a couple of different ways
that those merges can be performed in the general sense. For
the sake of simplicity and with the goal of at least providing
something concrete in this section of the
book, we'll assume that there is but a single vendor branch
which is upgraded to each successive new release of the
third-party library by receiving updates that describe the
differences between the current and new pristine versions of
that library.

Note

Another approach is to create new vendor branches for
each successive pristine library version, applying the
differences between the current pristine library and the
customized version thereof (from the current vendor branch)
to the new branch. There's nothing wrong with that
approach—we just don't feel compelled to document
every legitimate possibility in this space.

The following sections examine how to create and manage a
vendor branch in a few different scenarios. In the examples
which follow, we'll assume that the third-party library is
called libcomplex, and that we will be implementing a vendor
branch based on libcomplex 1.0.0 which lives in our repository
at ^/vendor/libcomplex-custom. We'll
then look at how we can upgrade to libcomplex 1.0.1 while
still preserving our customizations to the library.

Vendor Branches from Foreign Repositories

Let's look first at a vendor branch management approach
that is possible when the original third-party library is
itself Subversion-accessible. For the sake of the example,
we'll assume that the libcomplex library we previously
discussed is developed in a publicly accessible Subversion
repository, and that its developers use sane release
procedures which include the creation of tags for each stable
release version.

Since Subversion 1.5, svn merge
has been able to perform so-called foreign
repository merges, where the sources of the merge
live in a different repository than the repository from which
the merge target working copy was checked out. And in
Subversion 1.8, the behavior of svn copy
was changed so that when you perform a copy from a foreign
repository into an existing working copy, the resulting tree
is incorporated into that working copy and scheduled for
addition. It's this foreign repository
copy functionality that we'll use to bootstrap our
vendor branch.

So let's create our vendor branch. We'll begin by
creating a placeholder directory for all such vendor branches
in our repository, and then checking out a working copy of
that location.

Now, we'll take advantage of Subversion's foreign
repository copy support to get an exact copy of libcomplex
1.0.0—including any Subversion properties stored on its
files and directories—from the vendor repository.

If you happen to be using an older version of
Subversion, the closest available approximation of the new
foreign repository copy support in svn
copy is to instead import (via svn
import) a working copy of the vendor's tag,
including the --no-auto-props
and --no-ignore options so that the
complete tree and any of its versioned properties are
accurately replicated in your own repository.

Now that we have a vendor branch based on libcomplex 1.0.0,
we can begin making the customizations to libcomplex required
for our purposes, committing them directly to the vendor
branch we've created. And of course, we can begin using
libcomplex in our own application.

Some time later, libcomplex 1.0.1 is released. After
reviewing its changes, we decide we'd like to upgrade our
vendor branch to the new version. Here is where Subversion's
foreign repository merge operation is useful. We have in our
vendor branch the original libcomplex 1.0.0 plus our
customizations to it. What we need now is to get the set of
changes the vendor has made between 1.0.0 and 1.0.1 into our
vendor branch, ideally without clobbering our own
customizations. This is precisely what the 2-URL form of
the svn merge command is for.

As you can see, svn merge has merged
the changes required to make libcomplex 1.0.0 look like
libcomplex 1.0.1 into our working copy. In our example, it has
even noticed and flagged a conflict on one file. It seems
the vendor modified a region of one of the files we also
customized. Subversion safely detects this conflict, and
gives us the opportunity to resolve it so that our
customizations to what is now libcomplex 1.0.1 continue to
make sense. (See the section called “Resolve Any Conflicts”
for more on resolving conflicts of this sort.)

Once we've resolved the conflicts and performed any
testing or review we need, we can commit the changes to our
vendor branch.

That, in a nutshell, is how to manage vendor branches when
the original source is Subversion-accessible. There are some
notable shortcomings, though. First, foreign repository
merges are not automatically tracked by Subversion itself like
same-repository merges are. This means the burden falls to
the user to know which merges have been performed on their
vendor branch, and just how to construct the next merge when
upgrading that branch. Also, as is the case for all of
Subversion's merge support, renames in the merge sources can
cause no small amount of complication and frustration.
Unfortunately, at this time, we don't have a particularly
solid recommendation to offer to alleviate that pain.

Vendor Branches from Mirrored Sources

In the previous section
(the section called “Vendor Branches from Foreign Repositories”) we
looked at how to implement and maintain a vendor branch when
the vendor drops are accessible via Subversion, which is the
ideal scenario when it comes to vendor branches. Subversion
is pretty good at handling merges of stuff that's been
Subversion-managed. Unfortunately, it's not always the case
that third-party libraries are publicly accessible via
Subversion. Many times, a project depends on a library which
is delivered via only non-Subversion mechanisms, such as a
source code release distribution tarball. In such
circumstances, we strongly recommend that you do all you can
to get that non-Subversion information into Subversion as
cleanly as possible. So let's examine an approach to vendor
branches in which the third-party library's various releases
are mirrored within our own repository.

Setting up the vendor branch the first time is pretty
simple, really. For our example, we'll assume that libcomplex
1.0.0 is delivered via the common tarball mechanism. To
create our vendor branch, we'll first get the contents of the
libcomplex 1.0.0 tarball into our repository as a read-only
(by convention only) vendor tag of sorts.

Note that in our example, we used
the --no-ignore option during import so that
Subversion is sure to pick up every file in the vendor drop
and not to omit any of them. We also supply
the --no-auto-props option so that our client
doesn't manufacture property information which isn't present
in the vendor drop.[44].

Now that the first vendor release drop is present in our
repository, we can create our vendor branch from it just as we
would create any other branch—using svn
copy.

Okay. At this point we have a vendor branch based on
libcomplex 1.0.0. We are now poised to begin making the
customizations to libcomplex required for our
purposes—committing them directly to the vendor branch
we've created—and then to start using our customized
libcomplex in our own application.

Some time later, libcomplex 1.0.1 is released. After
reviewing its changes, we decide we'd like to upgrade our
vendor branch to the new version. In order to perform that
upgrade on our branch, we need to essentially apply the same
set of changes the vendor has made between 1.0.0 and 1.0.1 to
our vendor branch without clobbering our own customizations.
The safest way to perform that application is to first get
libcomplex 1.0.1 into our repository as a delta
against the libcomplex 1.0.0 code in our
repository. Afterwards, we'll use the 2-URL form
of the svn merge command to replicate those
same changes into our vendor branch.

As it turns out, there are several different approaches we
can take to to get libcomplex 1.0.1 into our repository in the
right way.[45] The approach we'll describe here
is relatively rudimentary, but it will serve our illustrative
needs.

Remember, we want our mirror of the libcomplex 1.0.1
vendor drop to share ancestry with our 1.0.0 vendor drop,
which will produce the best results later when we need to
merge the changes between those drops to our vendor branch.
So we'll start by creating a libcomplex-1.0.1 branch as copy
of our previously created libcomplex-1.0.0 “vendor
tag”—a copy which will eventually become a
replica of libcomplex 1.0.1.

What we need now is to make a working copy of our
libcomplex-1.0.1 branch, and then to make it actually look
like libcomplex 1.0.1. To do this, we'll take advantage of
the fact that svn checkout can overlay an
existing directory and, if the --force option
is provided, do so in manner that allows the differences
between the checked-out tree and the target tree that the
checkout overlayed to remain as local modifications in the new
working copy.

As you can see, after checking out what was really
libcomplex 1.0.0 atop the libcomplex 1.0.1 exploded tarball,
we are left with a working copy that contains local
modifications—those modifications required to morph our
previous vendor release drop into our new one.

Admittedly, this is a pretty simple example. The changes
required to perform this particular upgrade involved merely
content changes to existing files. In reality, new versions
of third-party libraries might also add or remove files or
directories, might rename files or directories, and so on. In
those situations, it can be much more challenging to morph the
new vendor tag into a state where it accurately reflects the
vendor drop it claims to reflect. We'll leave the details of
such transformations as an exercise to the
reader.[46]

However we make it happen, once our new vendor tag working
copy is reconciled with the original source distribution, we
can commit those changes to our repository.

We're finally ready to upgrade our vendor branch.
Remember, our goal is to get the changes made by the vendor
between the 1.0.0 and 1.0.1 releases of their library into our
vendor branch. There is where a 2-URL svn
merge operation, applied to a working copy of our
vendor branch, comes into play.

As you can see, svn merge has merged
the requisite changes into our working copy, flagging a
conflict where the vendor modified the same region of one of
the files as we did during our customizations. Subversion
detects this conflict, and gives us the opportunity to resolve
it (using the methods described in
the section called “Resolve Any Conflicts”) so that our
customizations to what is now libcomplex 1.0.1 continue to
make sense. Once we've resolved the conflicts and performed
any testing or review we need, we can commit the changes to
our vendor branch.