Tracking a Drupal distribution as a vendor branch in Subversion

Last updated on
30 September 2016

If you manage your own website code in Subversion, you may run into issues when you try and integrate an existing upstream code base that also uses Subversion. For code that you never intend to modify, svn externals can be useful for pulling in from an external Subversion repository directly. However, although we would of course never hack core, it is nevertheless sometimes required to make modifications to our local copies of Drupal distributions. For example, it's fairly common to make minor adjustments to files such as .htaccess or robots.txt. What to do?

This tutorial outlines how to use a technique called vendor branches, and how to make those vendor branches far less painful, with some helpful scripts. This mostly assumes you are running some flavor of *nix and are comfortable using the command-line.

start with the svn book:

(or 1.6)

If you read the bottom section and it makes sense to you - you are done; just make sure you have all the tools. If it doesn't really make sense, walk through this tutorial, then try again.


Make sure you have svn 1.5 or 1.6, that the CLI executable is in your path, and you are familiar with its operation.

On Linux, BSD, Sun, etc. you should be able to get some version of svn (at least 1.4) from your package manager.

For Mac users, OS 10.5 (Leopard) comes with svn 1.4, OS 10.6 (Snow Leopard) with svn 1.6. Svn 1.5+ is much preferred to 1.4 (though 1.4 is reasonably functional). Also, ensure XCode is installed to get important tools like diff, patch , cvs, etc.

If you still need to get svn, try:

Once you have svn installed and working from the terminal, use it to check out some contrib helper scripts for svn which probably don't come with your install. There are two that we care about:

* svn_load_dirs: This Perl script is designed to load a number of directories into Subversion. This is useful if you have a number of .zip's or tar.{Z,gz,bz2}'s for a particular package and want to load them into Subversion.

* svnmerge: Merge tracking script. Useful especially in environments where developers have mixed svn version from 1.4+. svn 1.5+ includes somewhat similar facilities.

see also:

For many Linux distributions these two scripts may be available from your package manager so you may want to check there. Ubuntu has both of these available under a package named subversion-tools.


sudo apt-get install subversion-tools
$ svn co
$ svn co


$ svn co
$ svn co

edit and make the following modifications:

a) Change the following line to the path of your svn command:

my $svn = '@SVN_BINDIR@/svn';

For example:

my $svn = '/usr/bin/svn';

b) You may optionally put your username and password in the script, but more likely you will pass it on the command line or set environment variables.

Save the file as just svn_load_dirs (or, and chmod 755
copy to svnmerge and chmod 755

Put these scripts into your path - e.g. you might use sudo to copy them to the same directory as svn, or maybe just copy to ~/bin depending on your config for PATH

sudo cp /usr/bin/svn_load_dirs
sudo cp /usr/bin/svnmerge

Optional Set-up

The first time you do this, you may want to use a throw-away repo. That's easy:

$ svnadmin create /tmp/trashrepo

Note: Your [svn-repo-path] in the steps below is then file:///tmp/trashrepo/

e.g. in the 1st step of the tutorial you'll do the command:

$ svn mkdir --parents -m"acquia-drupal" file:///tmp/trashrepo/vendor/acquia-drupal

though a more normal (remote) svn repo path might be

Initializing the vendor branch

Note: [svn-repo-path] is the URL to your repo, such as

From here, we will make a vendor branch of Acquia Drupal and show how to develop, deploy, and update it.

For illustration, we'll start with a historical release:

Download it somewhere you don't care about:

$ cd /tmp
$ wget
$ tar xzf acquia-drupal-

Make a vendor branch for this:

$ svn mkdir --parents -m"Acquia Drupal 1.2.20 (6.15 core)" [svn-repo-path]/vendor/acquia-drupal

Now, we import the Acquia Drupal code and tag it according to its version using svn_load_dirs.

Run the command without args to see its options:

$ svn_load_dirs

Typically, you may need to add additional arguments for the repo username and password: -svn_username and -svn_password

We will almost always want to use -t to get a tag directory that tags the specific imported set of code. This helps our vendor branch track alongside the upstream code.

$ svn_load_dirs -t 1.2.20 [svn-repo-path]/vendor/acqia-drupal current /tmp/acquia-drupal-1.2.20

It will prompt you, answer Y:

"Directory /tmp/acquia-drupal-1.2.20 will be tagged as 1.2.20
Please examine identified tags. Are they acceptable? (Y/n) "

Since this is the first time, it will prompt you, answer Y:

"The following directories do not exist and need to exist:
You must add them now to load the directories. Continue (Y/n)?"

Even running this locally will take a couple minutes. If you are committing to a remote repo - go get a beverage. This will commit the code from the tarball to the vendor branch as the "current" code, plus tag it.

Don't be alarmed if you see a lot of weird stuff that makes no sense, like /usr/bin/svn add -N --targets /var/folders/4l/4lsAYNNPFgOd7okDGS5KF++++TI/-Tmp-/svn_load_dirs_l1akxIugf9/targets.00001. This is normal.

When it's finished, you will be returned to the command prompt.

At this point in the repo will be two copies of Acquia Drupal:


Pulling vendor branch into trunk

Now you want to get ready to hack! Copy the vendor code to create a trunk directory:

$ svn cp -m"copy vendor code to trunk" [svn-repo-path]/vendor/acquia-drupal/current [svn-repo-path]/trunk

check out the trunk code, and cd into it:

$ svn co [svn-repo-path]/trunk
$ cd trunk

Now, we can initialize svnmerge. This will keep track of which revisions from the vendor branch have already been merged into trunk.

Since we just copied trunk from the vendor code, we don't need any detailed arguments to it. We will then diff to see the changes, and then commit using the message that svnmerge prepared for us..

$ svnmerge init

property 'svnmerge-integrated' set on '.'

$ svn diff

Property changes on: .
Added: svnmerge-integrated
+ /vendor/acquia-drupal/current:1-4

The range of revisions display by be different- essentially the starting rev of your repo before this tutorial through the last few commits that we just made.
This will create an automated commit message in the file svnmerge-commit-message.txt, which reads something like:

Initialized merge tracking via "svnmerge" with revisions "1-4" from

Commit the changes, using this file as the commit message:

$ svn ci -F svnmerge-commit-message.txt
$ svn up

Now you can hack - change .htaccess, add contrib modules or themes, etc. Just like your normal svn workflow.


$ nano .htaccess
$ svn ci -m"add new rewrite rule"
$ svn up
$ svn mkdir sites/all/modules
$ svn ci -m"add directory for contrib modules"
$ svn up

and maybe install Drupal so settings.php gets your credentials, and commit that if that's your workflow.

Updating the vendor branch

Now we see that there is a new version of Acquia Drupal available. So we want to get all the updates it includes without losing any of the changes or additions we made.

We essentially repeat the set of commands we used for the initial import. We get the new code and then import it into the "current" vendor code and tag the specific version:

$ cd /tmp
$ wget
$ tar xzf acquia-drupal-
$ svn_load_dirs -t 1.2.21 [svn-repo-path]/vendor/acquia-drupal current /tmp/acquia-drupal-1.2.21

In general you will answer "Y" to questions again. You may also be promoted if files have been added or removed. This gives you the option to tell svn_load_dirs that one or more of the changes were actually a file being renamed, rather than 2 different files where one is removed and another added. This improves the options for tracking the revision history of the code. If you get this prompt and all changes are simple deletes or adds, answer "F" for finished.

get back to your checked-out working copy, update it, and examine the available revisions to merge:

$ cd trunk/
$ svn up
$ svnmerge avail


In this case, we have just committed a single new revision of the vendor code, so there is only one revision to merge.

$ svnmerge merge

--- Merging r15 into '.':
U modules/acquia/apachesolr/
U modules/acquia/apachesolr/apachesolr.install
U modules/acquia/apachesolr/apachesolr_search.module
U modules/acquia/apachesolr/Drupal_Apache_Solr_Service.php
property 'svnmerge-integrated' set on '.'

Check that the changes look right - it's possible that you will have to manually resolve conflict if you hacked core (just say no) or changed a part of .htaccess that core changed.

$ svn stat
$ svn diff <some file I'm not sure about>

If all looks good, commit the merge using the message from svnmerge - you are up to date!

$ svn ci -F svnmerge-commit-message.txt
$ svn up