<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:html="http://www.w3.org/1999/html" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>Ross Burton</title><link>http://www.burtonini.com/blog</link><description>A potted account of Ross' life</description><language>en</language><ttl>60</ttl><dc:creator>Ross Burton</dc:creator><admin:generatorAgent rdf:resource="http://pyblosxom.sourceforge.net/"/><admin:errorReportsTo rdf:resource="mailto:ross@burtonini.com"/><item><title>Vendor Branches in Subversion</title><guid isPermaLink="false">computers/svn-vendor-2005-05-04-13-55</guid><link>http://www.burtonini.com/blog/computers/svn-vendor-2005-05-04-13-55</link><description>Subversion vendor branches are something I've always ignored. Over the years I've developed a healthy fear of branching and merging, ...</description><content:encoded><![CDATA[    <p>
      <a href="http://www.burtonini.com/photos/200503-India/img_1648.jpg" class="noline" style="float: right">
        <img src="http://www.burtonini.com/photos/200503-India/thumb-img_1648.jpg" class="thumbnail">
      </a> Subversion vendor branches are something I've always ignored.  Over
      the years I've developed a healthy fear of branching and merging, although
      it is common in developing Sound Juicer.  Systems like Arch make it less
      scary as it keep track of atomic changesets, so making it harder to loose
      half of a change, but I'm using Subversion at the moment until Bazaar or
      bzr-ng is convincing enough (and well documented enough) for me to switch.
      Of course, at some point I knew I I'd need to use vendor branches but I
      put off learning exactly how they work (beyond "you branch and merge and
      it works") until I needed to.  That point happened last week.
    </p>
    <p>
      I read the Subversion book, which confused me a bit and pointed me towards
      <tt>svn_load_dirs</tt>, which has both a man page and a README, neither of
      which make a great deal of sense.  So here I presume my summary, titled
      Vendor Branches In Subversion Without The Scary Details You Don't Need To
      Know.
    </p>
    <p>
      Step 1 is to grab a copy of the upstream source.  If you are taking
      snapshots from CVS use <tt>cvs export</tt> and not <tt>cvs checkout</tt>,
      otherwise you'll be committing the <tt>CVS/</tt> directories into
      Subversion.
    </p>
    <blockquote><tt>$ cvs export -r HEAD -d foo-20050504 foo</tt></blockquote>
    <p>
      This will grab a copy the <tt>foo</tt> module from the tip, and put it
      into a directory called <tt>foo-20050504</tt>.  As this is an exported
      copy of the source and not a checkout you cannot run any CVS commands on
      it, but that is not a problem as it will be deleted again in a few minutes.
    </p>
    <p>
      If the upstream source is a tarball, extract it and make sure these is
      nothing hanging around which should not be in Subversion (such as
      generated files).  Now to import it into Subversion.
    </p>
    <blockquote><tt>$ svn_load_dirs svn+ssh://svn/repos/foo/ -t upstream/foo-20050504 upstream/current foo-20050504/</tt></blockquote>
    <p>
      This needs some explaining.  The first argument is the location of the
      repository, I assume that this has already been created.  The second
      argument specifies that this import should be tagged
      <tt>upstream/foo-20050504</tt>, the third argument specifies the location
      to import the source too (<tt>upstream/current</tt>), and the forth and
      final argument is the path locally to import. Running this command will
      result in it asking a few questions to verify the tags, and then will
      churn for a few minutes as it does the import.
    </p>
    <p>
      You'll want to import into a vaguely named directory such as
      <tt>current</tt> so that Subversion keeps a history of the upstream
      changes.  Creating a tag for each version imported is essential for
      sanity: it will be used later on and if anything breaks it is trivial to
      extract known-good versions.
    </p>
    <p>
      Now that the source is imported, it is time to create a local branch.
    </p>
    <blockquote><tt>$ svn copy svn+ssh://svn/repos/foo/upstream/foo-20050504 svn+ssh://svn/repos/foo/trunk -m "Bring foo-20050504 into main branch"</tt></blockquote>
    <p>
      This makes a copy of the imported source into <tt>/trunk/</tt>, which you
      can happily hack away on.
    </p>
    <p>
      <cite>time passes...</cite>
    </p>
    <p>
      Now it's the 1<sup>st</sup> June, and there is a new copy of Foo to be
      imported.  Again, get a pristine copy and repeat the
      <tt>svn_load_dirs</tt>.
    </p>
    <blockquote><tt>$ svn_load_dirs svn+ssh://svn/repos/foo/ -t upstream/foo-20050601 upstream/current foo-20050601/</tt></blockquote>
    <p>
      This is where the magic really happens.  <tt>svn_load_dirs</tt> will grab
      the current copy of <tt>current</tt> and compare it with the new drop.  If
      there are any deleted or added files it will show them to you, so you can
      identify any file renames (thus both preserving history and saving space).
      It will then commit the new files into Subversion, and create a new tag.
      Then you can go into your working copy of <tt>trunk</tt> and merge the
      upstream changes with your own.
    </p>
    <blockquote><tt>$ svn merge svn+ssh://svn/repos/foo/upstream/foo-20050504 svn+ssh://svn/repos/foo/upstream/current</tt></blockquote>
    <p>
      This command will get the changes made in inbetween the 20050504 drop and
      the latest drop, and apply them to the current working directory.  There
      are bound to be a few conflicts so resolve those, and then commit.
    </p>
    <blockquote><tt>$ svn commit -m "Merged foo 200601 into trunk"</tt></blockquote>
    <p>
      All done.  Now you should go back and read the Subversion book and
      <tt>svn_load_dirs</tt> manual page, and I can ensure you they'll make a
      lot more sense this time.
    </p>
    <p>
      <small>NP: <cite>If You Can't Join Them, Beat Them</cite>, DJ Format</small>
    </p>
]]></content:encoded><dc:date>2005-05-04T12:55:00Z</dc:date></item></channel></rss>