[svnbook] r4361 committed - Finish issue 182 ("ch04: Rework vendor branch section. Entirely.")...

svnbook at googlecode.com svnbook at googlecode.com
Fri Jan 25 11:02:13 CST 2013


Revision: 4361
Author:   cmpilato at gmail.com
Date:     Fri Jan 25 09:01:58 2013
Log:      Finish issue 182 ("ch04: Rework vendor branch section. Entirely.")

* en/book/ch04-branching-and-merging.xml
   (svn.advanced.vendorbr): Completely rework this section and its  
subsections.
http://code.google.com/p/svnbook/source/detail?r=4361

Modified:
  /trunk/en/book/ch04-branching-and-merging.xml

=======================================
--- /trunk/en/book/ch04-branching-and-merging.xml	Thu Jan 24 14:00:59 2013
+++ /trunk/en/book/ch04-branching-and-merging.xml	Fri Jan 25 09:01:58 2013
@@ -3674,7 +3674,7 @@
    <!-- =================================================================  
-->
    <!-- =================================================================  
-->
    <sect1 id="svn.advanced.vendorbr">
-    <title>Tracking Third-Party Data</title>
+    <title>Vendor Branches</title>

      <para>As is especially the case when developing software, the data
        that you maintain under version control is often closely related
@@ -3752,65 +3752,15 @@
      <para>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—unfortunately—none of which
-      is a sort of <quote>silver bullet</quote> 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.</para>
+      and disadvantages, and none of which can be clearly considered
+      a <quote>silver bullet</quote> 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.</para>

      <!-- ===============================================================  
-->
-    <sect2 id="svn.advanced.vendorbr.read-only-mirroring">
-      <title>Read-only Mirroring of Third-party Data</title>
-
-      <para>The simplest scenario which involves vendor branches is
-        when that branch is more like a vendor tag—you never
-        modify the third-party library yourself, and are merely
-        mirroring it in your own repository for convenience.
-        Subversion offers various approaches to this.</para>
-
-      <para>For example, if the third-party library is itself already
-        available via Subversion, you can use Subversion's
-        <command>svnsync</command> tool to quite literally mirror the
-        whole third-party repository—or a portion
-        thereof—with a local repository (see
-        <xref linkend="svn.reposadmin.maint.replication" />).  Or, if
-        you wanted to merge the third-party library's history into the
-        same repository you use for your own codebase, you could
-        use <command>svnrdump dump</command> with <command>svnadmin
-        load --parent-dir</command> to replicate the history of the
-        third-party codebase into a subdirectory of your own
-        repository.  (We cover the use of <command>svnrdump</command>
-        in <xref linkend="svn.reposadmin.maint.migrate.svnrdump"
-        />.)</para>
-
-      <para>Often, you don't need the full history (every single
-        revision) of the vendor's data, but are only interested in
-        stable snapshots thereof.  The <command>svn import</command>
-        subcommand is designed specifically for quickly adding to
-        version control whole trees of locally unversioned
-        information, such as the contents of a vendor's source code
-        release archive file.  Alternatively, if the third-party
-        library is already Subversion-accessible, <command>svn
-        export</command> can create just such a local unversioned
-        directory tree—from, say, a tag in the vendor's
-        repository—that <command>svn import</command> can then
-        stash in your own repository.</para>
-
-      <para>Whatever approach you use, simply tracking in a read-only
-        manner a collection of information provided by another vendor
-        is relatively easy in Subversion.  It's when you need to
-        maintain customizations to that data that things become more
-        challenging.</para>
-
-    </sect2>
-
-    <!-- ===============================================================  
-->
-    <sect2 id="svn.advanced.vendorbr.customizing">
-      <title>Vendor Branches</title>
-
-      <para>Depending on third-party data can be a minor hassle.  But
-        depending on third-party data which needs to be tweaked for
-        your own purposes can be downright complicated.</para>
+    <sect2 id="svn.advanced.vendorbr.general">
+      <title>General Vendor Branch Management Procedure</title>

        <para>Maintaining customizations to a third-party library
          involves three data sources: the version of the third-party
@@ -3831,10 +3781,10 @@
          the sake of simplicity and with the goal of at least providing
          <emphasis>something</emphasis> concrete in this section of the
          book, we'll assume that there is but a single vendor branch
-        which is rebased against each successive new release of the
-        third-party library on which it is based by receiving updates
-        that describe the differences between the current and new
-        pristine versions of that library.</para>
+        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.</para>

        <note>
          <para>Another approach is to create new vendor branches for
@@ -3843,139 +3793,415 @@
            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.</para>
+          every legitimate possibility in this space.</para>
        </note>

-      <para>Let's continue looking into how to manage our vendor
-        branches.  In the examples which follow, we'll assume that the
-        third-party library is called libcomplex, and that we've
-        implemented a vendor branch based on libcomplex 1.0 which
-        lives in our repository
-        at <filename>^/vendor/libcomplex/custom</filename>.  We'll
-        be looking at how we can upgrade to libcomplex 1.1 while still
-        preserving our customizations to the library.</para>
+      <para>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 <filename>^/vendor/libcomplex-custom</filename>.  We'll
+        then look at how we can upgrade to libcomplex 1.0.1 while
+        still preserving our customizations to the library.</para>

-      <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  
-->
-      <sect3 id="svn.advanced.vendorbr.customizing.from-svn">
-        <title>Vendor branches from Subversion sources</title>
+    </sect2>

-        <para>When a vendor branch is based on third-party code that
-          is delivered via Subversion, the 2-URL form of
-          the <command>svn merge</command> command is probably the
-          best option for rebasing your vendor branch.  Since
-          Subversion 1.5, <command>svn merge</command> has even been
-          able to perform so-called <quote>foreign repository
-          merges</quote>, where the sources of the merge live in a
-          different repository than the repository from which the
-          merge target working copy was checked
-          out.<footnote><para>There are some notable limitations with
-          foreign repository merges, such as the lack of merge
-          tracking support, but those shouldn't affect the vendor
-          branch maintenance procedure discussed
-          here.</para></footnote> Let's assume that the pristine 1.0
-          and 1.1 versions of libcomplex are already available in our
-          own repository, imported
-          at <filename>^/vendor/libcomplex/1.0</filename>
-          and <filename>^/vendor/libcomplex/1.1</filename>,
-          respectively.</para>
+    <!-- ===============================================================  
-->
+    <sect2 id="svn.advanced.vendorbr.foreign-repos">
+      <title>Vendor Branches from Foreign Repositories</title>

-        <para>In order to get the changes made between versions 1.0
-          and 1.1 of libcomplex into our vendor branch, we must first
-          have a working copy of that branch.</para>
+      <para>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.</para>

-        <informalexample>
-          <screen>
-$ svn co http://svn.example.com/projects/repos/vendor/libcomplex/custom \
-         libcomplex-custom
+      <para>Since Subversion 1.5, <command>svn merge</command> has
+        been able to perform so-called <firstterm>foreign repository
+        merges</firstterm>, 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 <command>svn copy</command> 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 <firstterm>foreign repository copy</firstterm>
+        functionality that we'll use to bootstrap our vendor
+        branch.</para>
+
+      <para>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.</para>
+
+      <informalexample>
+        <screen>
+$ svn mkdir http://svn.example.com/projects/vendor \
+            -m "Create a container for vendor branches."
+Committed revision 1160.
+$ svn checkout http://svn.example.com/projects/vendor \
+               /path/to/vendor
+Checked out revision 1160.
+$
+</screen>
+      </informalexample>
+
+      <para>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.</para>
+
+      <informalexample>
+        <screen>
+$ cd /path/to/vendor
+$ svn copy http://svn.othervendor.com/repos/libcomplex/tags/1.0.0 \
+           libcomplex-custom
+--- Copying from foreign repository  
URL 'http://svn.othervendor.com/repos/lib\
+complex/tags/1.0.0':
  A    libcomplex-custom
  A    libcomplex-custom/README
  A    libcomplex-custom/LICENSE
  …
-A    libcomplex-custom/src/code.h
  A    libcomplex-custom/src/code.c
+A    libcomplex-custom/tests
  A    libcomplex-custom/tests/TODO
-Checked out revision 1156.
+$ svn commit -m "Initialize libcomplex vendor branch from libcomplex  
1.0.0."
+Adding         libcomplex-custom
+Adding         libcomplex-custom/README
+Adding         libcomplex-custom/LICENSE
+…
+Adding         libcomplex-custom/src
+Adding         libcomplex-custom/src/code.h
+Adding         libcomplex-custom/src/code.c
+Transmitting file data .......................................
+Committed revision 1161.
  $
  </screen>
-        </informalexample>
+      </informalexample>

-        <para>This working copy already contains our customized
-          version of libcomplex 1.0.  So, upgrading to libcomplex 1.1 is
-          a simple matter of applying the difference between 1.0 and 1.1
-          to our working copy.  That's pretty much exactly
-          what <command>svn merge</command> is made for.</para>
+      <note>
+        <para>If you happen to be using an older version of
+          Subversion, the closest available approximation of the new
+          foreign repository copy support in <command>svn
+          copy</command> is to instead import (via <command>svn
+          import</command>) a working copy of the vendor's tag,
+          including the <option>--no-auto-props</option>
+          and <option>--no-ignore</option> options so that the
+          complete tree and any of its versioned properties are
+          accurately replicated in your own repository.</para>
+      </note>

-        <informalexample>
-          <screen>
-$ cd /path/to/libcomplex-custom
-$ svn merge --ignore-ancestry \
-            ^/vendor/libcomplex/1.0 \
-            ^/vendor/libcomplex/1.1
---- Merging differences between repository URLs into '.':
-A    src/new-module
-A    src/new-module/init.c
-A    src/new-module/header.h
-…
-U    src/code.h
-C    src/code.c
-U    README
+      <para>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.</para>
+
+      <para>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 <command>svn merge</command> command is for.</para>
+
+      <informalexample>
+        <screen>
+$ cd /path/to/vendor
+$ svn merge http://svn.othervendor.com/repos/libcomplex/tags/1.0.0 \
+            http://svn.othervendor.com/repos/libcomplex/tags/1.0.1 \
+            libcomplex-custom
+--- Merging differences between foreign repository URLs into '.':
+U    libcomplex-custom/src/code.h
+C    libcomplex-custom/src/code.c
+U    libcomplex-custom/README
  Summary of conflicts:
    Text conflicts: 1
-Conflict discovered in file 'src/code.c'.
+Conflict discovered in file 'libcomplex-custom/src/code.c'.
  Select: (p) postpone, (df) diff-full, (e) edit, (m) merge,
          (mc) mine-conflict, (tc) theirs-conflict, (s) show all options:
  </screen>
-        </informalexample>
+      </informalexample>

-        <para>The first thing to note is that we used
-          the <option>--ignore-ancestry</option> option with
-          our <command>svn merge</command> command.  This is required
-          because in our repository, the
-          <filename>^/vendor/libcomplex/1.0</filename>
-          and <filename>^/vendor/libcomplex/1.1</filename> branches
-          share no common ancestry—both were fresh imports of
-          the respective libcomplex source release tarballs.  Had we
-          omitted this option, <command>svn merge</command> would have
-          determine that the safest way to transform the 1.0 tree into
-          the 1.1 tree would be to simply delete the former and add
-          the latter, with disastrous results in out working
-          copy.</para>
+      <para>As you can see, <command>svn merge</command> 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 <xref linkend="svn.tour.cycle.resolve" />
+        for more on resolving conflicts of this sort.)</para>

-        <para>Notice also that <command>svn merge</command> was able
-          to flag a conflict which arose from the merge.  It seems
-          that the libcomplex development team changed one or more
-          regions of <filename>src/code.c</filename> that we had
-          previously customized.  Fortunately, Subversion gives us the
-          change to resolve those conflicts so that our customizations
-          continue to make sense within the context of the upgraded
-          libcomplex codebase.</para>
+      <para>Once we've resolved the conflicts and performed any
+        testing or review we need, we can commit the changes to our
+        vendor branch.</para>

-        <para>Once all conflicts have been resolved, and we've
-          reviewed and tested the vendor branch code for correctness,
-          we can commit the results of our merge.  Our vendor branch
-          is now up-to-date with libcomplex 1.1!</para>
+      <informalexample>
+        <screen>
+$ svn status libcomplex-custom
+M       libcomplex-custom/src/code.h
+M       libcomplex-custom/src/code.c
+M       libcomplex-custom/README
+$ svn commit -m "Upgrade vendor branch to libcomplex 1.0.1." \
+             libcomplex-custom
+Sending        libcomplex-custom/README
+Sending        libcomplex-custom/src/code.h
+Sending        libcomplex-custom/src/code.c
+Transmitting file data ...
+Committed revision 1282.
+$
+</screen>
+      </informalexample>

-        <para>We mentioned previously that Subversion can also perform
-          such merges when the pristine vendor data lives in a
-          different repository.  We use the same syntax for such a
-          merge, except that we refer to the foreign repository URLs
-          and <emphasis>shouldn't</emphasis> need to use
-          the <option>--ignore-ancestry</option> option (because the
-          tags in the vendor's repository
-          probably <emphasis>do</emphasis> share a common
-          ancestry):</para>
+      <para>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.</para>

-        <informalexample>
-          <screen>
-$ cd /path/to/libcomplex-custom
-$ svn merge http://svn.othervendor.com/repos/libcomplex/tags/1.0 \
-            http://svn.othervendor.com/repos/libcomplex/tags/1.1
---- Merging differences between foreign repository URLs into '.':
-A    src/new-module
-A    src/new-module/init.c
-A    src/new-module/header.h
+    </sect2>
+
+    <!-- ===============================================================  
-->
+    <sect2 id="svn.advanced.vendorbr.mirrored-sources">
+      <title>Vendor Branches from Mirrored Sources</title>
+
+      <para>In the previous section
+        (<xref linkend="svn.advanced.vendorbr.foreign-repos" />) 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.</para>
+
+      <para>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.</para>
+
+      <informalexample>
+        <screen>
+$ tar xvfz libcomplex-1.0.0.tar.gz
+libcomplex-1.0.0/
+libcomplex-1.0.0/README
+libcomplex-1.0.0/LICENSE
  …
+libcomplex-1.0.0/src/code.c
+libcomplex-1.0.0/tests
+libcomplex-1.0.0/tests/TODO
+$ svn import libcomplex-1.0.0 \
+             http://svn.example.com/projects/vendor/libcomplex-1.0.0 \
+             --no-ignore --no-auto-props \
+             -m "Import libcomplex 1.0.0 sources."
+Adding         libcomplex-custom
+Adding         libcomplex-custom/README
+Adding         libcomplex-custom/LICENSE
+…
+Adding         libcomplex-custom/src
+Adding         libcomplex-custom/src/code.h
+Adding         libcomplex-custom/src/code.c
+Transmitting file data .......................................
+Committed revision 1160.
+$
+</screen>
+      </informalexample>
+
+      <para>Note that in our example, we used
+        the <option>--no-ignore</option> 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 <option>--no-auto-props</option> option so that our client
+        doesn't manufacture property information which isn't present
+        in the vendor drop.<footnote><para>Technically, we could let
+        the auto-props feature do its thing, but the key to making
+        that work well is ensuring that each vendor drop gets
+        identical auto-prop treatment.</para></footnote>.</para>
+
+      <para>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 <command>svn
+        copy</command>.</para>
+
+      <informalexample>
+        <screen>
+$ svn copy http://svn.example.com/projects/vendor/libcomplex-1.0.0 \
+           http://svn.example.com/projects/vendor/libcomplex-custom \
+           -m "Initialize libcomplex vendor branch from libcomplex 1.0.0."
+Committed revision 1161.
+$
+</screen>
+      </informalexample>
+
+      <para>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.</para>
+
+      <para>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 <emphasis>as a delta
+        against the libcomplex 1.0.0 code in our
+        repository</emphasis>.  Afterwards, we'll use the 2-URL form
+        of the <command>svn merge</command> command to replicate those
+        same changes into our vendor branch.</para>
+
+      <para>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.<footnote><para>Using another <command>svn
+        import</command> operation would be
+        an <emphasis>incorrect</emphasis> approach, as the libcomplex
+        1.0.0 and 1.0.1 branches would not have any common
+        ancestry.</para></footnote>  The approach we'll describe here
+        is relatively rudimentary, but it will serve our illustrative
+        needs.</para>
+
+      <para>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 <quote>vendor
+        tag</quote>—a copy which will eventually become a
+        replica of libcomplex 1.0.1.</para>
+
+      <informalexample>
+        <screen>
+$ svn copy http://svn.example.com/projects/vendor/libcomplex-1.0.0 \
+           http://svn.example.com/projects/vendor/libcomplex-1.0.1 \
+           -m "Setup a construction zone for libcomplex 1.0.1."
+Committed revision 1282.
+$
+</screen>
+      </informalexample>
+
+      <para>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 <command>svn checkout</command> can overlay an
+        existing directory and, if the <option>--force</option> 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.</para>
+
+      <informalexample>
+        <screen>
+$ tar xvfz libcomplex-1.0.1.tar.gz
+libcomplex-1.0.1/
+libcomplex-1.0.1/README
+libcomplex-1.0.1/LICENSE
+…
+libcomplex-1.0.1/src/code.c
+libcomplex-1.0.1/tests
+libcomplex-1.0.1/tests/TODO
+$ svn checkout http://svn.example.com/projects/vendor/libcomplex-1.0.1 \
+               libcomplex-1.0.1 \
+               --force
+E    libcomplex-1.0.1/README
+E    libcomplex-1.0.1/LICENSE
+E    libcomplex-1.0.1/INSTALL
+…
+E    libcomplex-1.0.1/src/code.c
+E    libcomplex-1.0.1/tests
+E    libcomplex-1.0.1/tests/TODO
+Checked out revision 1282.
+$ svn status libcomplex-1.0.1
+M       libcomplex-1.0.1/src/code.h
+M       libcomplex-1.0.1/src/code.c
+M       libcomplex-1.0.1/README
+$
+</screen>
+      </informalexample>
+
+      <para>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.</para>
+
+      <para>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.</para>
+
+      <para>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.</para>
+
+      <informalexample>
+        <screen>
+$ svn commit -m "Upgrade vendor branch to libcomplex 1.0.1." \
+             libcomplex-custom
+Sending        libcomplex-custom/README
+Sending        libcomplex-custom/src/code.h
+Sending        libcomplex-custom/src/code.c
+Transmitting file data ...
+Committed revision 1283.
+$
+</screen>
+      </informalexample>
+
+      <para>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 <command>svn
+        merge</command> operation, applied to a working copy of our
+        vendor branch, comes into play.</para>
+
+      <informalexample>
+        <screen>
+$ svn checkout http://svn.example.com/projects/vendor/libcomplex-custom \
+               libcomplex-custom
+E    libcomplex-custom/README
+E    libcomplex-custom/LICENSE
+E    libcomplex-custom/INSTALL
+…
+E    libcomplex-custom/src/code.c
+E    libcomplex-custom/tests
+E    libcomplex-custom/tests/TODO
+Checked out revision 1283.
+$ cd libcomplex-custom
+$ svn merge ^/vendor/libcomplex-1.0.0 \
+            ^/vendor/libcomplex-1.0.1
+--- Merging differences between URLs into '.':
  U    src/code.h
  C    src/code.c
  U    README
@@ -3985,29 +4211,41 @@
  Select: (p) postpone, (df) diff-full, (e) edit, (m) merge,
          (mc) mine-conflict, (tc) theirs-conflict, (s) show all options:
  </screen>
-        </informalexample>
+      </informalexample>

-        <para>As you can see, Subversion provides the same essential
-          functionality.</para>
+      <para>As you can see, <command>svn merge</command> 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
+        <xref linkend="svn.tour.cycle.resolve" />) 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.</para>

-        <para>Admittedly, this is a pretty simple use-case.
-          <command>svn merge</command> is pretty good about handling
-          content modifications and simple tree changes (additions and
-          deletions).  Unfortunately, things quickly devolve into
-          madness when files or directories have been renamed.  This
-          is still an area in which Subversion needs to improve.</para>
+      <informalexample>
+        <screen>
+$ svn status
+M       src/code.h
+M       src/code.c
+M       README
+$ svn commit -m "Upgrade vendor branch to libcomplex 1.0.1."
+Sending        README
+Sending        src/code.h
+Sending        src/code.c
+Transmitting file data ...
+Committed revision 1284.
+$
+</screen>
+      </informalexample>

-      </sect3>
+      <para>Our vendor branch upgrade is complete.  And the next time
+        we need to upgrade that branch, we'll follow the same
+        procedure we used to upgrade it this time.</para>

-      <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  
-->
-      <sect3 id="svn.advanced.vendorbr.customizing.from-non-svn">
-        <title>Vendor branches from non-Subversion sources</title>
-
-        <para>### TODO ###</para>
-
-      </sect3>
      </sect2>
-
    </sect1>

    <!-- =================================================================  
-->




More information about the svnbook-dev mailing list