Sophie

Sophie

distrib > Mageia > 6 > x86_64 > media > core-updates > by-pkgid > e8fe8188cee5592550f08a19b470186d > files > 50

subversion-doc-1.9.7-1.mga6.x86_64.rpm

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Advanced Merging</title>
    <link rel="stylesheet" type="text/css" href="styles.css" />
    <meta name="generator" content="DocBook XSL Stylesheets V1.76.1" />
    <style type="text/css">
body { background-image: url('images/draft.png');
       background-repeat: no-repeat;
       background-position: top left;
       /* The following properties make the watermark "fixed" on the page. */
       /* I think that's just a bit too distracting for the reader... */
       /* background-attachment: fixed; */
       /* background-position: center center; */
     }</style>
    <link rel="home" href="index.html" title="Version Control with Subversion [DRAFT]" />
    <link rel="up" href="svn.branchmerge.html" title="Chapter 4. Branching and Merging" />
    <link rel="prev" href="svn.branchmerge.basicmerging.html" title="Basic Merging" />
    <link rel="next" href="svn.branchmerge.switchwc.html" title="Traversing Branches" />
  </head>
  <body>
    <div xmlns="" id="vcws-version-notice">
      <p>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
       <a href="http://www.svnbook.com/">http://www.svnbook.com/</a>
       for stable versions of this book.</p>
    </div>
    <div class="navheader">
      <table width="100%" summary="Navigation header">
        <tr>
          <th colspan="3" align="center">Advanced Merging</th>
        </tr>
        <tr>
          <td width="20%" align="left"><a accesskey="p" href="svn.branchmerge.basicmerging.html">Prev</a> </td>
          <th width="60%" align="center">Chapter 4. Branching and Merging</th>
          <td width="20%" align="right"> <a accesskey="n" href="svn.branchmerge.switchwc.html">Next</a></td>
        </tr>
      </table>
      <hr />
    </div>
    <div class="sect1" title="Advanced Merging">
      <div class="titlepage">
        <div>
          <div>
            <h2 class="title" style="clear: both"><a id="svn.branchmerge.advanced"></a>Advanced Merging</h2>
          </div>
        </div>
      </div>
      <p>Here ends the automated magic.  Sooner or later, once you
      get the hang of branching and merging, you're going to have to
      ask Subversion to merge <span class="emphasis"><em>specific</em></span> changes
      from one place to another.  To do this, you're going to
      have to start passing more complicated arguments to <span class="command"><strong>svn
      merge</strong></span>.  The next section describes the fully expanded
      syntax of the command and discusses a number of common
      scenarios that require it.</p>
      <div class="sect2" title="Cherrypicking">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.cherrypicking"></a>Cherrypicking</h3>
            </div>
          </div>
        </div>
        <p>
        <a id="idp12491248" class="indexterm"></a>Just as the term <span class="quote">“<span class="quote">changeset</span>”</span> is often used in
        version control systems, so is the term
        <em class="firstterm">cherrypicking</em>.  This word refers to
        the act of choosing <span class="emphasis"><em>one</em></span> specific
        changeset from a branch and replicating it to another.
        Cherrypicking may also refer to the act of duplicating a
        particular set of (not necessarily contiguous!) changesets
        from one branch to another.  This is in contrast to more
        typical merging scenarios, where the <span class="quote">“<span class="quote">next</span>”</span>
        contiguous range of revisions is duplicated
        automatically.</p>
        <p>Why would people want to replicate just a single change?
        It comes up more often than you'd think.  For example, let's
        assume you've created a new feature branch <code class="filename">
        /calc/branches/my-calc-feature-branch</code> copied from
        <code class="filename">/calc/trunk</code>:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn log ^/calc/branches/new-calc-feature-branch -v -r403
------------------------------------------------------------------------
r403 | user | 2013-02-20 03:26:12 -0500 (Wed, 20 Feb 2013) | 1 line
Changed paths:
   A /calc/branches/new-calc-feature-branch (from /calc/trunk:402)

Create a new calc branch for Feature 'X'.
------------------------------------------------------------------------
</pre>
        </div>
        <p>At the water cooler, you get word that Sally made an interesting
        change to <code class="filename">main.c</code> on the trunk.
        Looking over the history of commits to the trunk, you see that
        in revision 413 she fixed a critical bug that directly
        impacts the feature you're working on.  You might not be ready
        to merge all the trunk changes to your branch just yet, but
        you certainly need that particular bug fix in order to continue
        your work.</p>
        <div class="informalexample">
          <pre class="screen">
$ svn log ^/calc/trunk -r413 -v
------------------------------------------------------------------------
r413 | sally | 2013-02-21 01:57:51 -0500 (Thu, 21 Feb 2013) | 3 lines
Changed paths:
   M /calc/trunk/src/main.c

Fix issue #22 'Passing a null value in the foo argument
of bar() should be a tolerated, but causes a segfault'.
------------------------------------------------------------------------

$ svn diff ^/calc/trunk -c413
Index: src/main.c
===================================================================
--- src/main.c  (revision 412)
+++ src/main.c  (revision 413)
@@ -34,6 +34,7 @@
…
# Details of the fix
…
</pre>
        </div>
        <p>Just as you used <span class="command"><strong>svn diff</strong></span> in the prior
        example to examine revision 413, you can pass the same option
        to <span class="command"><strong>svn merge</strong></span>:</p>
        <div class="informalexample">
          <pre class="screen">
$ cd new-calc-feature-branch

$ svn merge ^/calc/trunk -c413
--- Merging r413 into '.':
U    src/main.c
--- Recording mergeinfo for merge of r413 into '.':
 U   .

$ svn st
 M      .
M       src/main.c
</pre>
        </div>
        <p>You can now go through the usual testing procedures before
        committing this change to your branch.  After the commit,
        Subversion updates the <code class="literal">svn:mergeinfo</code> on your
        branch to reflect that r413 was been merged to the branch.  This
        prevents future automatic sync merges from attempting to merge
        r413 again.  (Merging the same change to the same branch almost
        always results in a conflict!) Notice also the mergeinfo <code class="literal">
        /calc/branches/my-calc-branch:341-379</code>.  This was
        recorded during the earlier reintegrate merge to <code class="filename">
        /calc/trunk</code> from the <code class="filename">
        /calc/branches/my-calc-branch</code> branch which we made in
        r380.  When we created the <code class="filename">my-calc-branch</code>
        branch in r403, this mergeinfo was carried along with the copy.
        </p>
        <div class="informalexample">
          <pre class="screen">
$ svn pg svn:mergeinfo -v
Properties on '.':
  svn:mergeinfo
    /calc/branches/my-calc-branch:341-379
    /calc/trunk:413
</pre>
        </div>
        <p>Notice too that the <span class="command"><strong>mergeinfo</strong></span> doesn't list r413
        as "eligible" to merge, because it's already been merged:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn mergeinfo ^/calc/trunk --show-revs eligible
r404
r405
r406
r407
r409
r410
r411
r412
r414
r415
r416
…
r455
r456
r457
</pre>
        </div>
        <p>The preceding means that when the time finally comes to do an
        automatic sync merge, Subversion breaks the merge into two parts.
        First it merges all eligible merges up to revision 412.  Then it
        merges all eligible revisions from revisions 414 to the <code class="literal">HEAD
        </code> revision.  Because we already cherrypicked r413, that
        change is skipped:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn merge ^/calc/trunk
--- Merging r403 through r412 into '.':
U    doc/INSTALL
U    src/main.c
U    src/button.c
U    src/integer.c
U    Makefile
U    README
--- Merging r414 through r458 into '.':
G    doc/INSTALL
G    src/main.c
G    src/integer.c
G    Makefile
--- Recording mergeinfo for merge of r403 through r458 into '.':
 U   .
</pre>
        </div>
        <p>
        <a id="idp12516608" class="indexterm"></a>This use case of replicating
        (or <em class="firstterm">backporting</em>) bug fixes from one
        branch to another is perhaps the most popular reason for
        cherrypicking changes; it comes up all the time, for example,
        when a team is maintaining a <span class="quote">“<span class="quote">release branch</span>”</span> of
        software.  (We discuss this pattern in
        <a class="xref" href="svn.branchmerge.commonpatterns.html#svn.branchmerge.commonpatterns.release" title="Release Branches">the section called “Release Branches”</a>.)</p>
        <div class="warning" title="Warning" style="margin-left: 0.5in; margin-right: 0.5in;">
          <table border="0" summary="Warning">
            <tr>
              <td rowspan="2" align="center" valign="top" width="25">
                <img alt="[Warning]" src="images/warning.png" />
              </td>
              <th align="left">Warning</th>
            </tr>
            <tr>
              <td align="left" valign="top">
                <p>Did you notice how, in the last example, the merge
          invocation merged two distinct ranges?
          The <span class="command"><strong>svn merge</strong></span> command applied
          two independent patches to your working copy to skip over
          changeset 413, which your branch already contained.  There's
          nothing inherently wrong with this, except that it has the
          potential to make conflict resolution trickier.  If the
          first range of changes creates conflicts,
          you <span class="emphasis"><em>must</em></span> resolve them interactively for
          the merge process to continue and apply the second range of
          changes.  If you postpone a conflict from the first wave of
          changes, the whole merge command will bail out with an error
          message and you must resolve the conflict before running the
          merge a second time to get the remainder of the changes.</p>
              </td>
            </tr>
          </table>
        </div>
        <p>A word of warning: while <span class="command"><strong>svn diff</strong></span> and
        <span class="command"><strong>svn merge</strong></span> are very similar in concept, they
        do have different syntax in many cases.  Be sure to read about
        them in <a class="xref" href="svn.ref.svn.html" title="svn Reference—Subversion Command-Line Client">svn Reference—Subversion Command-Line Client</a> for details, or ask
        <span class="command"><strong>svn help</strong></span>.  For example, <span class="command"><strong>svn
        merge</strong></span> requires a working copy path as a target, that is,
        a place where it should apply the generated patch.  If the
        target isn't specified, it assumes you are trying to perform
        one of the following common operations:</p>
        <div class="itemizedlist">
          <ul class="itemizedlist" type="disc">
            <li class="listitem">
              <p>You want to merge directory changes into your current
            working directory.</p>
            </li>
            <li class="listitem">
              <p>You want to merge the changes in a specific file into
            a file by the same name that exists in your current working
            directory.</p>
            </li>
          </ul>
        </div>
        <p>If you are merging a directory and haven't specified a
        target path, <span class="command"><strong>svn merge</strong></span> assumes the first
        case and tries to apply the changes into your current
        directory.  If you are merging a file, and that file (or a
        file by the same name) exists in your current working
        directory,
        <span class="command"><strong>svn merge</strong></span> assumes the second case and tries
        to apply the changes to a local file with the same name.</p>
      </div>
      <div class="sect2" title="Merge Syntax: Full Disclosure">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.advanced.advancedsyntax"></a>Merge Syntax: Full Disclosure</h3>
            </div>
          </div>
        </div>
        <p>You've now seen some examples of the <span class="command"><strong>svn
        merge</strong></span> command, and you're about to see several more.
        If you're feeling confused about exactly how merging works,
        you're not alone.  Many users (especially those new to version
        control) are initially perplexed about the proper syntax of
        the command and about how and when the feature should be
        used.  But fear not, this command is actually much simpler
        than you think!  There's a very easy technique for
        understanding exactly how <span class="command"><strong>svn merge</strong></span>
        behaves.</p>
        <p>The main source of confusion is the
        <span class="emphasis"><em>name</em></span> of the command.  The term
        <span class="quote">“<span class="quote">merge</span>”</span> somehow denotes that branches are
        combined together, or that some sort of mysterious
        blending of data is going on.  That's not the case.  A better
        name for the command might have been <span class="command"><strong>svn
        diff-and-apply</strong></span>, because that's all that happens:
        two repository trees are compared, and the differences are
        applied to a working copy.</p>
        <p>If you're using <span class="command"><strong>svn merge</strong></span> to do basic
        copying of changes between branches, an automatic merge will
        generally do the right thing.  For example, a command such as the
        following,</p>
        <div class="informalexample">
          <pre class="screen">
$ svn merge ^/calc/branches/some-branch
</pre>
        </div>
        <p>will attempt to duplicate any changes made
        on <code class="filename">some-branch</code> into your current working
        directory, which is presumably a working copy that shares some
        historical connection to the branch.  The command is smart
        enough to only duplicate changes that your working copy
        doesn't yet have.  If you repeat this command once a week, it
        will only duplicate the <span class="quote">“<span class="quote">newest</span>”</span> branch changes
        that happened since you last merged.</p>
        <p>If you choose to use the <span class="command"><strong>svn merge</strong></span>
        command in all its full glory by giving it specific revision
        ranges to duplicate, the command takes three main
        arguments:</p>
        <div class="orderedlist">
          <a id="idp12544560" class="indexterm"></a>
          <a id="idp12546048" class="indexterm"></a>
          <a id="idp12547536" class="indexterm"></a>
          <ol class="orderedlist" type="1">
            <li class="listitem">
              <p>An initial repository tree (often called the
            <em class="firstterm">left side</em> of the comparison)</p>
            </li>
            <li class="listitem">
              <p>A final repository tree (often called the
            <em class="firstterm">right side</em> of the
            comparison)</p>
            </li>
            <li class="listitem">
              <p>A working copy to accept the differences as local
            changes (often called the <em class="firstterm">target</em> of
            the merge)</p>
            </li>
          </ol>
        </div>
        <p>Once these three arguments are specified, then the two trees
        are compared and the differences applied to the
        target working copy as local modifications.  When the command
        is done, the results are no different than if you had
        hand-edited the files or run various <span class="command"><strong>svn
        add</strong></span> or <span class="command"><strong>svn delete</strong></span> commands
        yourself.  If you like the results, you can commit them.  If
        you don't like the results, you can simply <span class="command"><strong>svn
        revert</strong></span> all of the changes.</p>
        <p>The syntax of <span class="command"><strong>svn merge</strong></span> allows you to
        specify the three necessary arguments rather flexibly.  Here
        are some examples:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn merge http://svn.example.com/repos/branch1@150 \
            http://svn.example.com/repos/branch2@212 \
            my-working-copy

$ svn merge -r 100:200 http://svn.example.com/repos/trunk my-working-copy

$ svn merge -r 100:200 http://svn.example.com/repos/trunk
</pre>
        </div>
        <p>The first syntax lays out all three arguments explicitly,
        naming each tree in the form <span class="emphasis"><em>URL@REV</em></span> and
        naming the working copy target.  The second syntax is used
        as a shorthand for situations when you're comparing two
        different revisions of the same URL.
        <a id="idp12559600" class="indexterm"></a> This type of merge is referred to (for obvious
        reasons) as a <span class="quote">“<span class="quote">2-URL</span>”</span> merge. The last syntax shows
        how the working copy argument is optional; if omitted, it
        defaults to the current directory.</p>
        <p>While the first example shows the <span class="quote">“<span class="quote">full</span>”</span>
        syntax of <span class="command"><strong>svn merge</strong></span>, use it
        very carefully;  it can result in merges which do not record
        any <code class="literal">svn:mergeinfo</code> metadata at all.  The
        next section talks a bit more about this.</p>
      </div>
      <div class="sect2" title="Merges Without Mergeinfo">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.nomergedata"></a>Merges Without Mergeinfo</h3>
            </div>
          </div>
        </div>
        <p>Subversion tries to generate merge metadata whenever it
        can, to make future invocations of <span class="command"><strong>svn
        merge</strong></span> smarter.  There are still situations, however,
        where <code class="literal">svn:mergeinfo</code> data is not created or
        changed.  Remember to be a bit wary of these scenarios:</p>
        <div class="variablelist">
          <dl>
            <dt>
              <span class="term">Merging unrelated sources</span>
            </dt>
            <dd>
              <p>If you ask <span class="command"><strong>svn merge</strong></span> to compare
              two URLs that aren't related to each other, a patch is
              still generated and applied to your working copy, but
              no merging metadata is created.  There's no common
              history between the two sources, and
              future <span class="quote">“<span class="quote">smart</span>”</span> merges depend on that common
              history.</p>
            </dd>
            <dt>
              <span class="term">Merging from foreign repositories</span>
            </dt>
            <dd>
              <p>While it's possible to run a command such
              as <strong class="userinput"><code>svn merge -r 100:200
              <em class="replaceable"><code>http://svn.foreignproject.com/repos/trunk</code></em></code></strong>,
              the resultant patch also lacks any historical merge
              metadata.  At the time of this writing, Subversion has no
              way of representing different repository URLs within
              the <code class="literal">svn:mergeinfo</code> property.</p>
            </dd>
            <dt>
              <span class="term">Using <code class="option">--ignore-ancestry</code></span>
            </dt>
            <dd>
              <p>If this option is passed to <span class="command"><strong>svn
              merge</strong></span>, it causes the merging logic to
              mindlessly generate differences the same way
              that <span class="command"><strong>svn diff</strong></span> does, ignoring any
              historical relationships.  We discuss this later in this
              chapter in
              <a class="xref" href="svn.branchmerge.advanced.html#svn.branchmerge.advanced.ancestry" title="Noticing or Ignoring Ancestry">the section called “Noticing or Ignoring Ancestry”</a>.</p>
            </dd>
            <dt>
              <span class="term">Applying reverse merges from a target's natural history</span>
            </dt>
            <dd>
              <p>Earlier in this chapter
              (<a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.undo" title="Undoing Changes">the section called “Undoing Changes”</a>) we
              discussed how to use <span class="command"><strong>svn merge</strong></span> to
              apply a <span class="quote">“<span class="quote">reverse patch</span>”</span> as a way of rolling
              back changes.  If this technique is used to undo a
              change to an object's personal history (e.g., commit r5
              to the trunk, then immediately roll back r5
              using <strong class="userinput"><code>svn merge . -c -5</code></strong>), this
              sort of merge doesn't affect the recorded
              mergeinfo.<sup>[<a id="idp12583552" href="#ftn.idp12583552" class="footnote">41</a>]</sup></p>
            </dd>
          </dl>
        </div>
        <div class="sidebar" title="Natural History and Implicit Mergeinfo">
          <a id="svn.branchmerge.nomergedata.impicit.mergeinfo"></a>
          <div class="titlepage">
            <div>
              <div>
                <p class="title">
                  <strong>Natural History and Implicit Mergeinfo</strong>
                </p>
              </div>
            </div>
          </div>
          <p>
          <a id="idp12588240" class="indexterm"></a>
          <a id="idp12589728" class="indexterm"></a>As we mentioned earlier when discussing
          <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.mergeinfo.inheritance" title="Mergeinfo Inheritance">Mergeinfo Inheritance</a>,
          a path that has the
          <code class="literal">svn:mergeinfo</code> property set on it is said to
          have <span class="quote">“<span class="quote">explicit</span>”</span> mergeinfo.  Yes, this implies a
          path can have <span class="quote">“<span class="quote">implicit</span>”</span> mergeinfo, too!  Implicit
          mergeinfo, or <em class="firstterm">natural history</em>, is
          simply a path's own history (see
          <a class="xref" href="svn.tour.history.html" title="Examining History">the section called “Examining History”</a>) interpreted as mergeinfo.
          While implicit mergeinfo is largely
          an implementation detail, it can be a useful abstraction for
          understanding merge tracking behavior.</p>
          <p>Let's say you created <code class="filename">^/trunk</code> in
          revision 100 and then later, in revision 201,
          created <code class="filename">^/branches/feature-branch</code> as
          a copy of <code class="filename">^/trunk@200</code>.  The natural
          history of <code class="filename">^/branches/feature-branch</code>
          contains all the repository paths and revision ranges
          through which the history of the new branch has ever
          passed:</p>
          <div class="informalexample">
            <div class="literallayout">
              <p><br />
/trunk:100-200<br />
/branches/feature-branch:201<br />
</p>
            </div>
          </div>
          <p>With each new revision added to the repository, the
          natural history—and thus, implicit mergeinfo—of
          the branch continues to expand to include those revisions
          until the day the branch is deleted.  Here's what the
          implicit mergeinfo of our branch would look like when
          the <code class="literal">HEAD</code> revision of the repository had
          grown to 234:</p>
          <div class="informalexample">
            <div class="literallayout">
              <p><br />
/trunk:100-200<br />
/branches/feature-branch:201-234<br />
</p>
            </div>
          </div>
          <p>Implicit mergeinfo does not actually show up in the
          <code class="literal">svn:mergeinfo</code> property, but Subversion
          acts as if it does.  This is why if you check out
          <code class="filename">^/branches/feature-branch</code> and then
          run <strong class="userinput"><code>svn merge ^/trunk -c 58</code></strong> in the
          resulting working copy, nothing happens.  Subversion knows
          that the changes committed to <code class="filename">^/trunk</code>
          in revision 58 are already present in the target's natural
          history, so there's no need to try to merge them again.
          After all, avoiding repeated merges of
          changes <span class="emphasis"><em>is</em></span> the primary goal of
          Subversion's merge tracking feature!</p>
        </div>
      </div>
      <div class="sect2" title="More on Merge Conflicts">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.advanced.mergeconflicts"></a>More on Merge Conflicts</h3>
            </div>
          </div>
        </div>
        <p>Just like the <span class="command"><strong>svn update</strong></span> command,
        <span class="command"><strong>svn merge</strong></span> applies changes to your working
        copy.  And therefore it's also capable of creating
        conflicts.  The conflicts produced by <span class="command"><strong>svn
          merge</strong></span>, however, are sometimes different, and this
        section explains those differences.</p>
        <p>To begin with, assume that your working copy has no
        local edits.  When you <span class="command"><strong>svn update</strong></span> to a
        particular revision, the changes sent by the server
        always apply <span class="quote">“<span class="quote">cleanly</span>”</span> to your working copy.
        The server produces the delta by comparing two trees: a
        virtual snapshot of your working copy, and the revision tree
        you're interested in.  Because the left hand side of the
        comparison is exactly equal to what you already have, the
        delta is guaranteed to correctly convert your working copy
        into the right hand tree.</p>
        <p>But <span class="command"><strong>svn merge</strong></span> has no such guarantees
        and can be much more chaotic: the advanced user can ask the
        server to compare <span class="emphasis"><em>any</em></span> two trees at all,
        even ones that are unrelated to the working copy!  This means
        there's large potential for human error.  Users will sometimes
        compare the wrong two trees, creating a delta that doesn't
        apply cleanly. The <span class="command"><strong>svn merge</strong></span> subcommand does
        its best to apply as much of the delta as possible, but some
        parts may be impossible. A common sign that you merged the wrong
        delta is unexpected tree conflicts:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn merge ^/calc/trunk -r104:115
--- Merging r105 through r115 into '.':
   C doc
   C src/button.c
   C src/integer.c
   C src/real.c
   C src/main.c
--- Recording mergeinfo for merge of r105 through r115 into '.':
 U   .
Summary of conflicts:
  Tree conflicts: 5

$ svn st
 M      .
!     C doc
      &gt;   local dir missing, incoming dir edit upon merge
!     C src/button.c
      &gt;   local file missing, incoming file edit upon merge
!     C src/integer.c
      &gt;   local file missing, incoming file edit upon merge
!     C src/main.c
      &gt;   local file missing, incoming file edit upon merge
!     C src/real.c
      &gt;   local file missing, incoming file edit upon merge
Summary of conflicts:
  Tree conflicts: 5
</pre>
        </div>
        <p>In the previous example, it might be the case that
        <code class="filename">doc</code> and the four <code class="filename">*.c</code>
        files all exist in both snapshots of the
        branch being compared.  The resultant delta wants to change
        the contents of the corresponding paths in your working copy,
        but those paths don't exist in the working copy.  Whatever the
        case, the preponderance of tree conflicts most likely means that
        the user compared the wrong two trees or that you are merging to
        the wrong working copy target; both are classic signs of user
        error.  When this happens, it's easy to recursively revert all
        the changes created by the merge
        (<strong class="userinput"><code>svn revert . --recursive</code></strong>), delete any
        unversioned files or directories left behind after the
        revert, and rerun <span class="command"><strong>svn merge</strong></span> with the
        correct arguments.</p>
        <p>Also keep in mind that a merge into a working copy with no
        local edits can still produce text conflicts.</p>
        <div class="informalexample">
          <pre class="screen">
$ svn st

$ svn merge ^/paint/trunk -r289:291
--- Merging r290 through r291 into '.':
C    Makefile
--- Recording mergeinfo for merge of r290 through r291 into '.':
 U   .
Summary of conflicts:
  Text conflicts: 1
Conflict discovered in file 'Makefile'.
Select: (p) postpone, (df) diff-full, (e) edit, (m) merge,
        (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: p

$ svn st
 M      .
C       Makefile
?       Makefile.merge-left.r289
?       Makefile.merge-right.r291
?       Makefile.working
Summary of conflicts:
  Text conflicts: 1
</pre>
        </div>
        <p>How can a conflict possibly happen?  Again, because the user
        can request <span class="command"><strong>svn merge</strong></span> to define and apply any
        old delta to the working copy, that delta may contain textual
        changes that don't cleanly apply to a working file, even if
        the file has no local modifications.</p>
        <p>Another small difference between <span class="command"><strong>svn
        update</strong></span> and <span class="command"><strong>svn merge</strong></span> is the names
        of the full-text files created when a conflict happens.  In
        <a class="xref" href="svn.tour.cycle.html#svn.tour.cycle.resolve" title="Resolve Any Conflicts">the section called “Resolve Any Conflicts”</a>, we saw that an
        update produces files named
        <code class="filename">filename.mine</code>,
        <code class="filename">filename.rOLDREV</code>, and
        <code class="filename">filename.rNEWREV</code>.  When <span class="command"><strong>svn
        merge</strong></span> produces a conflict, though, it creates three
        files named <code class="filename">filename.working</code>,
        <code class="filename">filename.merge-left.rOLDREV</code>, and
        <code class="filename">filename.merge-right.rNEWREV</code>.  In this case,
        the terms <span class="quote">“<span class="quote">merge-left</span>”</span> and <span class="quote">“<span class="quote">merge-right</span>”</span>
        are describing which side of the double-tree comparison the file
        came from, <span class="quote">“<span class="quote">rOLDREV</span>”</span> describes the revision of the
        left side, and <span class="quote">“<span class="quote">rNEWREV</span>”</span> the revision of the right
        side. In any case, these differing names help you distinguish
        between conflicts that happened as a result of an  update and
        ones that happened as a result of a merge.</p>
      </div>
      <div class="sect2" title="Blocking Changes">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.advanced.blockchanges"></a>Blocking Changes</h3>
            </div>
          </div>
        </div>
        <p>Sometimes there's a particular changeset that you don't
        want automatically merged.  For example, perhaps your
        team's policy is to do new development work on
        <code class="filename">/trunk</code>, but is more conservative about
        backporting changes to a stable branch you use for releasing
        to the public.  On one extreme, you can manually cherrypick
        single changesets from the trunk to the branch—just the
        changes that are stable enough to pass muster.  Maybe things
        aren't quite that strict, though; perhaps most of the time
        you just let <span class="command"><strong>svn merge</strong></span>
        automatically merge most changes from trunk to branch.  In
        this case, you want a way to mask a few specific changes
        out, that is, prevent them from ever being automatically
        merged.</p>
        <p>To block a changeset you must make Subversion believe that the
        change has <span class="emphasis"><em>already</em></span> been merged.  To do this,
        invoke the merge subcommand with the <code class="option">--record-only</code>
        option.  The option makes Subversion record mergeinfo as if it had
        actually performed the merge, but no difference is actually
        applied:</p>
        <div class="informalexample">
          <pre class="screen">
$ cd my-calc-branch

$ svn merge ^/calc/trunk -r386:388 --record-only
--- Recording mergeinfo for merge of r387 through r388 into '.':
 U   .

# Only the mergeinfo is changed
$ svn st
 M      .

$ svn pg svn:mergeinfo -vR
Properties on '.':
  svn:mergeinfo
    /calc/trunk:341-378,387-388

$ svn commit -m "Block r387-388 from being merged to my-calc-branch."
Sending        .

Committed revision 461.
</pre>
        </div>
        <p>Since Subversion 1.7, <code class="option">--record-only</code>
        merges are transitive.  This means that, in addition to recording
        mergeinfo describing the blocked revision(s), any
        <code class="literal">svn:mergeinfo</code> property differences in the
        merge source are also applied.  For example, let's say we want to
        block the 'paint-python-wrapper' feature from ever being merged from
        <code class="filename">^/paint/trunk</code> to the
        <code class="filename">^/paint/branches/paint-1.0.x</code> branch.  We know
        the work on this feature was done on its own branch, which was
        reintegrated to <code class="filename">/paint/trunk</code> in revision
        465:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn log -v -r465 ^/paint/trunk
------------------------------------------------------------------------
r465 | joe | 2013-02-25 14:05:12 -0500 (Mon, 25 Feb 2013) | 1 line
Changed paths:
   M /paint/trunk
   A /paint/trunk/python (from /paint/branches/paint-python-wrapper/python:464)

Reintegrate Paint Python wrapper.
------------------------------------------------------------------------
</pre>
        </div>
        <p>Because revision 465 was a reintegrate merge we know
        that mergeinfo was recorded describing the merge:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn diff ^/paint/trunk --depth empty -c465
Index: .
===================================================================
--- .   (revision 464)
+++ .   (revision 465)

Property changes on: .
___________________________________________________________________
Added: svn:mergeinfo
   Merged /paint/branches/paint-python-wrapper:r463-464
</pre>
        </div>
        <p>Now simply blocking merges of revision 465 from
        <code class="filename">/paint/trunk</code> isn't foolproof since someone could
        merge r462:464 directly from
        <code class="filename">/paint/branches/paint-python-wrapper</code>.
        Fortunately the transitive nature
        of <code class="option">--record-only</code> merges prevents this; the
        <code class="option">--record-only</code> merge
        applies the <code class="literal">svn:mergeinfo</code> diff from
        revision 465, thus blocking merges of that change directly from
        <code class="filename">/paint/trunk</code> <span class="emphasis"><em>and</em></span> indirectly
        from <code class="filename">/paint/branches/paint-python-wrapper</code>:
        </p>
        <div class="informalexample">
          <pre class="screen">
$ cd paint/branches/paint-1.0.x

$ svn merge ^/paint/trunk --record-only -c465
--- Merging r465 into '.':
 U   .
--- Recording mergeinfo for merge of r465 into '.':
 G   .

$ svn diff --depth empty
Index: .
===================================================================
--- .   (revision 462)
+++ .   (working copy)

Property changes on: .
___________________________________________________________________
Added: svn:mergeinfo
   Merged /paint/branches/paint-python-wrapper:r463-464
   Merged /paint/trunk:r465

$ svn ci -m "Block the Python wrappers from the first release of paint."
Sending        .

Committed revision 466.
</pre>
        </div>
        <p>Now any subsequent attempts to merge the feature to <code class="filename">
        /paint/trunk</code> are inoperative:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn merge ^/paint/trunk -c465
--- Recording mergeinfo for merge of r465 into '.':
 U   .

$ svn st # No change!

$ svn merge ^/paint/branches/paint-python-wrapper -r462:464
--- Recording mergeinfo for merge of r463 through r464 into '.':
 U   .

$ svn st  # No change!

$
</pre>
        </div>
        <p>If at a later time you realize that you actually <span class="emphasis"><em>do
        </em></span> need the blocked feature merged to <code class="filename">/paint/trunk
        </code> you have a couple of choices.  You can reverse merge r466,
        (the revision you blocked the feature), as we discussed in
        <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.undo" title="Undoing Changes">the section called “Undoing Changes”</a>.  Once you commit
        that change you can repeat the merge of r465 from <code class="filename">
        /paint/trunk</code>.  Alternatively, you can simply repeat the
        merge of r465 from <code class="filename">/paint/trunk</code> using the
        <code class="option">--ignore-ancestry</code> option, which will cause the merge
        to disregard any mergeinfo and simply apply the requested diff, see
        <a class="xref" href="svn.branchmerge.advanced.html#svn.branchmerge.advanced.ancestry" title="Noticing or Ignoring Ancestry">the section called “Noticing or Ignoring Ancestry”</a>.</p>
        <div class="informalexample">
          <pre class="screen">
$ svn merge ^/paint/trunk -c465 --ignore-ancestry
--- Merging r465 into '.':
A    python
A    python/paint.py
 G   .
</pre>
        </div>
        <p>Blocking changes with <code class="option">--record-only</code>
        works, but it's also a little bit
        dangerous.  The main problem is that we're not clearly
        differentiating between the ideas of <span class="quote">“<span class="quote">I already have
        this change</span>”</span> and <span class="quote">“<span class="quote">I don't have this change, but
        don't currently want it.</span>”</span> We're effectively lying to
        the system, making it think that the change was previously
        merged.  This puts the responsibility on you—the
        user—to remember that the change wasn't actually merged,
        it just wasn't wanted.  There's no way to ask Subversion for a
        list of <span class="quote">“<span class="quote">blocked changelists.</span>”</span> If you want to
        track them (so that you can unblock them someday) you'll need
        to record them in a text file somewhere, or perhaps in an
        invented property.</p>
      </div>
      <div class="sect2" title="Merge-Sensitive Logs and Annotations">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.advanced.logblame"></a>Merge-Sensitive Logs and Annotations</h3>
            </div>
          </div>
        </div>
        <p>One of the main features of any version control system is
        to keep track of who changed what, and when they did it.
        The <span class="command"><strong>svn log</strong></span> and <span class="command"><strong>svn
        blame</strong></span> subcommands are just the tools for this: when
        invoked on individual files, they show not only the history of
        changesets that affected the file, but also exactly which user
        wrote which line of code, and when she did it.</p>
        <p>When changes start getting replicated between branches,
        however, things start to get complicated.  For example, if you
        were to ask <span class="command"><strong>svn log</strong></span> about the history of
        your feature branch, it would show exactly every revision that ever
        affected the branch:</p>
        <div class="informalexample">
          <pre class="screen">
$ cd my-calc-branch

$ svn log -q
------------------------------------------------------------------------
r461 | user | 2013-02-25 05:57:48 -0500 (Mon, 25 Feb 2013)
------------------------------------------------------------------------
r379 | user | 2013-02-18 10:56:35 -0500 (Mon, 18 Feb 2013)
------------------------------------------------------------------------
r378 | user | 2013-02-18 09:48:28 -0500 (Mon, 18 Feb 2013)
------------------------------------------------------------------------
…
------------------------------------------------------------------------
r8 | sally | 2013-01-17 16:55:36 -0500 (Thu, 17 Jan 2013)
------------------------------------------------------------------------
r7 | bill | 2013-01-17 16:49:36 -0500 (Thu, 17 Jan 2013)
------------------------------------------------------------------------
r3 | bill | 2013-01-17 09:07:04 -0500 (Thu, 17 Jan 2013)
------------------------------------------------------------------------
</pre>
        </div>
        <p>But is this really an accurate picture of all the changes
        that happened on the branch?  What's left out here is
        the fact that revisions 352, 362, 372 and 379 were actually the
        results of merging changes from the trunk.  If you look at one
        of these logs in detail, the multiple trunk changesets that
        comprised the branch change are nowhere to be seen:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn log ^/calc/branches/my-calc-branch -r352 -v
------------------------------------------------------------------------
r352 | user | 2013-02-16 09:35:18 -0500 (Sat, 16 Feb 2013) | 1 line
Changed paths:
   M /calc/branches/my-calc-branch
   M /calc/branches/my-calc-branch/Makefile
   M /calc/branches/my-calc-branch/doc/INSTALL
   M /calc/branches/my-calc-branch/src/button.c
   M /calc/branches/my-calc-branch/src/real.c

Sync latest trunk changes to my-calc-branch.
------------------------------------------------------------------------
</pre>
        </div>
        <p>We happen to know that this merge to the branch was
        nothing but a merge of trunk changes.  How can we see those
        trunk changes as well?  The answer is to use the
        <code class="option">--use-merge-history</code> (<code class="option">-g</code>)
        option.  This option expands those <span class="quote">“<span class="quote">child</span>”</span>
        changes that were part of the merge.</p>
        <div class="informalexample">
          <pre class="screen">
$ svn log ^/calc/branches/my-calc-branch -r352 -v -g
------------------------------------------------------------------------
r352 | user | 2013-02-16 09:35:18 -0500 (Sat, 16 Feb 2013) | 1 line
Changed paths:
   M /calc/branches/my-calc-branch
   M /calc/branches/my-calc-branch/Makefile
   M /calc/branches/my-calc-branch/doc/INSTALL
   M /calc/branches/my-calc-branch/src/button.c
   M /calc/branches/my-calc-branch/src/real.c

Sync latest trunk changes to my-calc-branch.
------------------------------------------------------------------------
r351 | sally | 2013-02-16 08:04:22 -0500 (Sat, 16 Feb 2013) | 2 lines
Changed paths:
   M /calc/trunk/src/real.c
Merged via: r352

Trunk work on calc project.
------------------------------------------------------------------------
…
------------------------------------------------------------------------
r345 | sally | 2013-02-15 16:51:17 -0500 (Fri, 15 Feb 2013) | 2 lines
Changed paths:
   M /calc/trunk/Makefile
   M /calc/trunk/src/integer.c
Merged via: r352

Trunk work on calc project.
------------------------------------------------------------------------
r344 | sally | 2013-02-15 16:44:44 -0500 (Fri, 15 Feb 2013) | 1 line
Changed paths:
   M /calc/trunk/src/integer.c
Merged via: r352

Refactor the bazzle functions.
------------------------------------------------------------------------
</pre>
        </div>
        <p>By making the log operation use merge history, we see not
        just the revision we queried (r352), but also the other revisions
        that came along on the ride with it—Sally's work on trunk.
        This is a much more complete picture of history!</p>
        <p>The <span class="command"><strong>svn blame</strong></span> command also takes the
        <code class="option">--use-merge-history</code> (<code class="option">-g</code>)
        option.  If this option is neglected, somebody looking at
        a line-by-line annotation of <code class="filename">Makefile</code> may
        get the mistaken impression that you were responsible for a
        particular change:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn blame src/button.c
…
   352    user    retval = inverse_func(button, path);
   352    user    return retval;
   352    user    }
…
</pre>
        </div>
        <p>And while it's true that you did actually commit those
        three lines in revision 352, two of them were actually written
        by Sally back in revision 348 and were brought into your branch
        via a sync merge:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn blame button.c -g
…
G    348    sally   retval = inverse_func(button, path);
G    348    sally   return retval;
     352    user    }
…
</pre>
        </div>
        <p>Now we know who to <span class="emphasis"><em>really</em></span> blame for
        those two lines of code!</p>
      </div>
      <div class="sect2" title="Noticing or Ignoring Ancestry">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.advanced.ancestry"></a>Noticing or Ignoring Ancestry</h3>
            </div>
          </div>
        </div>
        <p>
        <a id="idp12693200" class="indexterm"></a>When conversing with a Subversion developer, you
        might very likely hear reference to the term
        <em class="firstterm">ancestry</em>.  This word is used to
        describe the relationship between two objects in a
        repository: if they're related to each other, one
        object is said to be an ancestor of the other.</p>
        <p>For example, suppose you commit revision 100, which
        includes a change to a file <code class="filename">foo.c</code>.
        Then <code class="filename">foo.c@99</code> is an
        <span class="quote">“<span class="quote">ancestor</span>”</span> of <code class="filename">foo.c@100</code>.
        On the other hand, suppose you commit the deletion of
        <code class="filename">foo.c</code> in revision 101, and then add a
        new file by the same name in revision 102.  In this case,
        <code class="filename">foo.c@99</code> and
        <code class="filename">foo.c@102</code> may appear to be related
        (they have the same path), but in fact are completely
        different objects in the repository.  They share no history
        or <span class="quote">“<span class="quote">ancestry.</span>”</span></p>
        <p>The reason for bringing this up is to point out an
        important difference between <span class="command"><strong>svn diff</strong></span> and
        <span class="command"><strong>svn merge</strong></span>.  The former command ignores
        ancestry, while the latter command is quite sensitive to it.
        For example, if you asked <span class="command"><strong>svn diff</strong></span> to
        compare revisions 99 and 102 of <code class="filename">foo.c</code>,
        you would see line-based diffs; the <span class="command"><strong>diff</strong></span>
        command is blindly comparing two paths.  But if you asked
        <span class="command"><strong>svn merge</strong></span> to compare the same two objects,
        it would notice that they're unrelated and first attempt to
        delete the old file, then add the new file;  the output would
        indicate a deletion followed by an add:</p>
        <div class="informalexample">
          <pre class="screen">
D    foo.c
A    foo.c
</pre>
        </div>
        <p>Most merges involve comparing trees that are ancestrally
        related to one another; therefore, <span class="command"><strong>svn
        merge</strong></span> defaults to this behavior.  Occasionally,
        however, you may want the <span class="command"><strong>merge</strong></span> command to
        compare two unrelated trees.  For example, you may have
        imported two source-code trees representing different vendor
        releases of a software project (see
        <a class="xref" href="svn.advanced.vendorbr.html" title="Vendor Branches">the section called “Vendor Branches”</a>).  If you ask
        <span class="command"><strong>svn merge</strong></span> to compare the two trees, you'd
        see the entire first tree being deleted, followed by an add
        of the entire second tree!  In these situations, you'll want
        <span class="command"><strong>svn merge</strong></span> to do a path-based comparison
        only, ignoring any relations between files and directories.
        Add the <code class="option">--ignore-ancestry</code> option to your
        <span class="command"><strong>merge</strong></span> command, and it will behave just
        like <span class="command"><strong>svn diff</strong></span>.  (And conversely, the
        <code class="option">--notice-ancestry</code> option will cause
        <span class="command"><strong>svn diff</strong></span> to behave like the
        <span class="command"><strong>svn merge</strong></span> command.)</p>
        <div class="tip" title="Tip" style="margin-left: 0.5in; margin-right: 0.5in;">
          <table border="0" summary="Tip">
            <tr>
              <td rowspan="2" align="center" valign="top" width="25">
                <img alt="[Tip]" src="images/tip.png" />
              </td>
              <th align="left">Tip</th>
            </tr>
            <tr>
              <td align="left" valign="top">
                <p>
        <a id="idp12716336" class="indexterm"></a>
        The <code class="option">--ignore-ancestry</code> option also disables
        <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.mergetracking" title="Merge Tracking">Merge Tracking</a>.
        This means that <code class="literal">svn:mergeinfo</code> is not considered
        when <span class="command"><strong>svn merge</strong></span> is determining what revisions
        to merge, nor is <code class="literal">svn:mergeinfo</code> recorded to
        describe the merge.</p>
              </td>
            </tr>
          </table>
        </div>
      </div>
      <div class="sect2" title="Merges and Moves">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.advanced.moves"></a>Merges and Moves</h3>
            </div>
          </div>
        </div>
        <p>A common desire is to refactor source code, especially
        in Java-based software projects.  Files and directories are
        shuffled around and renamed, often causing great disruption
        to everyone working on the project.  Sounds like a perfect
        case to use a branch, doesn't it?  Just create a branch,
        shuffle things around, and then merge the branch back to the
        trunk, right?</p>
        <p>Alas, this scenario doesn't work so well right now and
        is considered one of Subversion's current weak spots.  The
        problem is that Subversion's <span class="command"><strong>svn merge</strong></span>
        command isn't as robust as it should be, particularly when
        dealing with copy and move operations.</p>
        <p>When you use <span class="command"><strong>svn copy</strong></span> to duplicate a
        file, the repository remembers where the new file came from,
        but it fails to transmit that information to the client which
        is running <span class="command"><strong>svn update</strong></span> or <span class="command"><strong>svn
        merge</strong></span>.  Instead of telling the client, <span class="quote">“<span class="quote">Copy
        that file you already have to this new location,</span>”</span> it
        sends down an entirely new file.  This can lead to
        problems, particularly tree conflicts in the case of renames,
        which involve not only the new copy, but a deletion of the old
        path—a lesser-known fact about Subversion is that
        it lacks <span class="quote">“<span class="quote">true renames</span>”</span>—the <span class="command"><strong>svn
        move</strong></span> command is nothing more than an aggregation
        of <span class="command"><strong>svn copy</strong></span> and <span class="command"><strong>svn
        delete</strong></span>.</p>
        <p>For example, suppose that you want to make some changes on
        your private branch <code class="filename">/calc/branch/my-calc-branch
        </code>.  First you perform an automatic sync merge with
        <code class="filename">/calc/trunk</code> and commit that in r470:</p>
        <div class="informalexample">
          <pre class="screen">
$ cd calc/trunk

$ svn merge ^/calc/trunk
--- Merging differences between repository URLs into '.':
U    doc/INSTALL
A    FAQ
U    src/main.c
U    src/button.c
U    src/integer.c
U    Makefile
U    README
 U   .
--- Recording mergeinfo for merge between repository URLs into '.':
 U   .

$ svn ci -m "Sync all changes from ^/calc/trunk through r469."
Sending        .
Sending        Makefile
Sending        README
Sending        FAQ
Sending        doc/INSTALL
Sending        src/main.c
Sending        src/button.c
Sending        src/integer.c
Transmitting file data ....
Committed revision 470.
</pre>
        </div>
        <p>Then you rename <code class="filename">integer.c</code> to <code class="filename">
        whole.c</code> in r471 and then make some edits to the same
        file in r473.  Effectively you've created a new file in your branch
        (that is a copy of the original file plus some edits) and deleted
        the original file.  Meanwhile, back on <code class="filename">/calc/trunk
        </code>, Sally has committed some improvements of her own to
        <code class="filename">integer.c</code> in r472:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn log -v -r472 ^/calc/trunk
------------------------------------------------------------------------
r472 | sally | 2013-02-26 07:05:18 -0500 (Tue, 26 Feb 2013) | 1 line
Changed paths:
   M /calc/trunk/src/integer.c

Trunk work on integer.c.
------------------------------------------------------------------------
</pre>
        </div>
        <p>Now you decide to merge your branch back to the trunk.
        How will Subversion combine the rename and edits you made
        with Sally's edits?</p>
        <div class="informalexample">
          <pre class="screen">
$ svn merge ^/calc/branches/my-calc-branch
--- Merging differences between repository URLs into '.':
   C src/integer.c
 U   src/real.c
A    src/whole.c
--- Recording mergeinfo for merge between repository URLs into '.':
 U   .
Summary of conflicts:
  Tree conflicts: 1

$ svn st
 M      .
      C src/integer.c
      &gt;   local file edit, incoming file delete upon merge
 M      src/real.c
A  +    src/whole.c
Summary of conflicts:
  Tree conflicts: 1
</pre>
        </div>
        <p>The answer is that Subversion <span class="emphasis"><em>won't</em></span>
        combine those changes, but rather raises a tree conflict<sup>[<a id="idp12742976" href="#ftn.idp12742976" class="footnote">42</a>]</sup>because it needs your help
        to figure out what part of your changes and what part of Sally's
        changes should ultimately end up in <code class="filename">whole.c</code>
        or even if the rename should take place at all!</p>
        <p>You will need to resolve this tree conflict before committing
        the merge and this may require some manual intervention on your
        part, see <a class="xref" href="svn.tour.treeconflicts.html" title="Dealing with Structural Conflicts">the section called “Dealing with Structural Conflicts”</a>.  The moral of
        this story is that until Subversion improves, be careful about
        merging copies and renames from one branch to another and when you
        do, be prepared for some manual resolution.</p>
      </div>
      <div class="sect2" title="Blocking Merge Tracking Unaware Clients">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.advanced.pre1.5clients"></a>Blocking Merge Tracking Unaware Clients</h3>
            </div>
          </div>
        </div>
        <p>If you've just upgraded your server to Subversion 1.5 or
        later, there's a risk that pre-1.5 Subversion
        clients can cause problems with
        <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.mergetracking" title="Merge Tracking">Merge Tracking</a>.
        This is because pre-1.5 clients don't support this feature;
        when one of these older clients performs <span class="command"><strong>svn
        merge</strong></span>, it doesn't modify the value of
        the <code class="literal">svn:mergeinfo</code> property at all.  So the
        subsequent commit, despite being the result of a merge,
        doesn't tell the repository about the duplicated
        changes—that information is lost.  Later on,
        when <span class="quote">“<span class="quote">merge-aware</span>”</span> clients attempt automatic
        merging, they're likely to run into all sorts of conflicts
        resulting from repeated merges.</p>
        <p>If you and your team are relying on the merge-tracking
        features of Subversion, you may want to configure your
        repository to prevent older clients from committing changes.
        The easy way to do this is by inspecting
        the <span class="quote">“<span class="quote">capabilities</span>”</span> parameter in
        the <code class="literal">start-commit</code> hook script.  If the
        client reports itself as having <code class="literal">mergeinfo</code>
        capabilities, the hook script can allow the commit to start.
        If the client doesn't report that capability, have the hook
        deny the commit.
        <a class="xref" href="svn.branchmerge.advanced.html#svn.branchmerge.advanced.hook-ex1" title="Example 4.1. Merge-tracking gatekeeper start-commit hook script">Example 4.1, “Merge-tracking gatekeeper start-commit hook script”</a> gives an
        example of such a hook script:</p>
        <div class="example">
          <a id="svn.branchmerge.advanced.hook-ex1"></a>
          <p class="title">
            <strong>Example 4.1. Merge-tracking gatekeeper start-commit hook script</strong>
          </p>
          <div class="example-contents">
            <pre class="programlisting">
#!/usr/bin/env python
import sys

# The start-commit hook is invoked immediately after a Subversion txn is
# created and populated with initial revprops in the process of doing a
# commit. Subversion runs this hook by invoking a program (script, 
# executable, binary, etc.) named 'start-commit' (for which this file
# is a template) with the following ordered arguments:
#
#   [1] REPOS-PATH   (the path to this repository)
#   [2] USER         (the authenticated user attempting to commit)
#   [3] CAPABILITIES (a colon-separated list of capabilities reported
#                     by the client; see note below)
#   [4] TXN-NAME     (the name of the commit txn just created)

capabilities = sys.argv[3].split(':')
if "mergeinfo" not in capabilities:
  sys.stderr.write("Commits from merge-tracking-unaware clients are "
                   "not permitted.  Please upgrade to Subversion 1.5 "
                   "or newer.\n")
  sys.exit(1)
sys.exit(0)
</pre>
          </div>
        </div>
        <br class="example-break" />
        <p>For more information about hook scripts, see
        <a class="xref" href="svn.reposadmin.create.html#svn.reposadmin.hooks" title="Implementing Repository Hooks">the section called “Implementing Repository Hooks”</a>.</p>
      </div>
      <div class="sect2" title="The Final Word on Merge Tracking">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.advanced.finalword"></a>The Final Word on Merge Tracking</h3>
            </div>
          </div>
        </div>
        <p>The bottom line is that Subversion's merge-tracking
        feature has an complex internal implementation, and
        the <code class="literal">svn:mergeinfo</code> property is the only
        window the user has into the machinery.</p>
        <p>How and when mergeinfo is recorded by a merge can sometimes
        be difficult to understand.  Furthermore, the management of
        mergeinfo metadata has a whole set of taxonomies and behaviors
        around it, such as <span class="quote">“<span class="quote">explicit</span>”</span> versus <span class="quote">“<span class="quote">implicit
        </span>”</span> mergeinfo, <span class="quote">“<span class="quote">operative</span>”</span>
        versus <span class="quote">“<span class="quote">inoperative</span>”</span> revisions, specific
        mechanisms of mergeinfo <span class="quote">“<span class="quote">elision,</span>”</span> and
        even <span class="quote">“<span class="quote">inheritance</span>”</span> from parent to child
        directories.</p>
        <p>We've chosen to only briefly cover, if at all, these detailed
        topics for a couple of reasons.  First, the level of detail is
        overwhelming for a typical user.  Second, and more
        importantly, the typical user <span class="emphasis"><em>doesn't</em></span> need
        to understand these concepts; typically they remain in the
        background as implementation details.  All that said, if you
        enjoy this sort of thing, you can get a fantastic overview in a
        paper posted at CollabNet's website: <a class="ulink" href="http://www.open.collab.net/community/subversion/articles/merge-info.html" target="_top">http://www.open.collab.net/community/subversion/articles/merge-info.html</a>.</p>
        <p>For now, if you want to steer clear of the complexities of
        merge tracking, we recommend that you follow these simple best
        practices:</p>
        <div class="itemizedlist">
          <ul class="itemizedlist" type="disc">
            <li class="listitem">
              <p>For short-term feature branches, follow the simple
            procedure described throughout
            <a class="xref" href="svn.branchmerge.basicmerging.html" title="Basic Merging">the section called “Basic Merging”</a>.</p>
            </li>
            <li class="listitem">
              <p>Avoid subtree merges and subtree mergeinfo. Perform
            merges only on the root of your branches, not on
            subdirectories or files (see <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.stayinsync.subtree" title="Subtree Merges and Subtree Mergeinfo">Subtree Merges and Subtree Mergeinfo</a>)
            .</p>
            </li>
            <li class="listitem">
              <p>Don't ever edit the <code class="literal">svn:mergeinfo</code>
            property directly; use <span class="command"><strong>svn
            merge</strong></span> with the <code class="option">--record-only</code> option
            to effect a desired change to the metadata (as demonstrated in
            <a class="xref" href="svn.branchmerge.advanced.html#svn.branchmerge.advanced.blockchanges" title="Blocking Changes">the section called “Blocking Changes”</a>).</p>
            </li>
            <li class="listitem">
              <p>Your merge target should be a working copy which
            represents the root of a <span class="emphasis"><em>complete</em></span> tree
            representing a <span class="emphasis"><em>single</em></span> location in the
            repository at a single point in time:
            </p>
              <div class="itemizedlist">
                <ul class="itemizedlist" type="circle">
                  <li class="listitem">
                    <p>Update before you merge!  Don't use the <code class="option">
                --allow-mixed-revisions</code> option to merge into
                mixed-revision working copies.</p>
                  </li>
                  <li class="listitem">
                    <p>Don't merge to targets with <span class="quote">“<span class="quote">switched</span>”</span>
                subdirectories (as described next in
                <a class="xref" href="svn.branchmerge.switchwc.html" title="Traversing Branches">the section called “Traversing Branches”</a>).</p>
                  </li>
                  <li class="listitem">
                    <p>Avoid merges to targets with sparse directories.
                  Likewise, don't merge to depths other than
                  <code class="option">--depth=infinity</code></p>
                  </li>
                  <li class="listitem">
                    <p>Be sure you have read access to all of the merge
                  source and read/write access to all of the merge
                  target.</p>
                  </li>
                </ul>
              </div>
              <p>
          </p>
            </li>
          </ul>
        </div>
        <p>Of course sometimes you may need to violate some of these
        best practices.  Don't worry if you need to, just be sure you
        understand the ramifications of doing so.</p>
      </div>
      <div class="footnotes">
        <br />
        <hr width="100" align="left" />
        <div class="footnote">
          <p><sup>[<a id="ftn.idp12583552" href="#idp12583552" class="para">41</a>] </sup>Interestingly, after rolling
              back a revision like this, we wouldn't be able to
              reapply the revision using <strong class="userinput"><code>svn merge . -c
              5</code></strong>, since the mergeinfo would already list r5
              as being applied.  We would have to use
              the <code class="option">--ignore-ancestry</code> option to make
              the merge command ignore the existing
              mergeinfo!</p>
        </div>
        <div class="footnote">
          <p><sup>[<a id="ftn.idp12742976" href="#idp12742976" class="para">42</a>] </sup>If Sally hadn't made her change in r472, then Subversion would
        notice that <code class="filename">integer.c</code> in the
        target working copy is identical to <code class="filename">integer.c</code>
        in the left-side of the merge and would allow your rename to
        succeed without a tree conflict:</p>
          <div class="informalexample">
            <pre class="screen">
$ svn merge ^/calc/branches/my-calc-branch
--- Merging differences between repository URLs into '.':
 U   src/real.c
A    src/whole.c
D    src/integer.c
--- Recording mergeinfo for merge between repository URLs into '.':
 U   .
</pre>
          </div>
        </div>
      </div>
    </div>
    <div class="navfooter">
      <hr />
      <table width="100%" summary="Navigation footer">
        <tr>
          <td width="40%" align="left"><a accesskey="p" href="svn.branchmerge.basicmerging.html">Prev</a> </td>
          <td width="20%" align="center">
            <a accesskey="u" href="svn.branchmerge.html">Up</a>
          </td>
          <td width="40%" align="right"> <a accesskey="n" href="svn.branchmerge.switchwc.html">Next</a></td>
        </tr>
        <tr>
          <td width="40%" align="left" valign="top">Basic Merging </td>
          <td width="20%" align="center">
            <a accesskey="h" href="index.html">Home</a>
          </td>
          <td width="40%" align="right" valign="top"> Traversing Branches</td>
        </tr>
      </table>
    </div>
    <div xmlns="" id="vcws-footer">
      <hr />
      <img src="images/cc-by.png" style="float: right;" />
      <p>You are reading <em>Version Control with Subversion</em> (for
       Subversion 1.8), by Ben Collins-Sussman, Brian W. Fitzpatrick,
       and C. Michael Pilato.</p>
      <p>This work is licensed under
       the <a href="http://creativecommons.org/licenses/by/2.0/">Creative Commons Attribution License v2.0</a>.</p>
      <p>To submit comments, corrections, or other contributions to the
       text, please visit <a href="http://www.svnbook.com/">http://www.svnbook.com/</a>.</p>
    </div>
  </body>
</html>