Sophie

Sophie

distrib > Mageia > 6 > i586 > media > core-updates > by-pkgid > d32d95698a59acd37b394f83dfc217c6 > files > 51

subversion-doc-1.9.7-1.mga6.i586.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>Basic 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.using.html" title="Using Branches" />
    <link rel="next" href="svn.branchmerge.advanced.html" title="Advanced Merging" />
  </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">Basic Merging</th>
        </tr>
        <tr>
          <td width="20%" align="left"><a accesskey="p" href="svn.branchmerge.using.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.advanced.html">Next</a></td>
        </tr>
      </table>
      <hr />
    </div>
    <div class="sect1" title="Basic Merging">
      <div class="titlepage">
        <div>
          <div>
            <h2 class="title" style="clear: both"><a id="svn.branchmerge.basicmerging"></a>Basic Merging</h2>
          </div>
        </div>
      </div>
      <p>Now you and Sally are working on parallel branches of the
      project: you're working on a private branch, and Sally is
      working on the trunk, or main line of development.</p>
      <p>For projects that have a large number of contributors, it's
      common for most people to have working copies of the trunk.
      Whenever someone needs to make a long-running change that is
      likely to disrupt the trunk, a standard procedure is to create a
      private branch and commit changes there until all the work is
      complete.</p>
      <p>So, the good news is that you and Sally aren't interfering
      with each other.  The bad news is that it's very easy to drift
      <span class="emphasis"><em>too</em></span> far apart.  Remember that one of the
      problems with the <span class="quote">“<span class="quote">crawl in a hole</span>”</span> strategy is
      that by the time you're finished with your branch, it may be
      near-impossible to merge your changes back into the trunk
      without a huge number of conflicts.</p>
      <p>
      <a id="idp12171776" class="indexterm"></a>Instead, you and Sally might continue to share changes as
      you work.  It's up to you to decide which changes are worth
      sharing; Subversion gives you the ability to selectively
      <span class="quote">“<span class="quote">copy</span>”</span> changes between branches.  And when you're
      completely finished with your branch, your entire set of branch
      changes can be copied back into the trunk.  In Subversion
      terminology, the general act of replicating changes from one
      branch to another is called <em class="firstterm">merging</em>, and
      it is performed using various invocations of the <span class="command"><strong>svn
      merge</strong></span> subcommand.</p>
      <p>In the examples that follow, we're assuming that both your
      Subversion client and server are running Subversion 1.8 (or
      later).  If either client or server is older than version 1.5,
      things are more complicated: the system won't track changes
      automatically, forcing you to use painful manual methods to
      achieve similar results.  That is, you'll always need to use the
      detailed merge syntax to specify specific ranges of revisions to
      replicate (see
      <a class="xref" href="svn.branchmerge.advanced.html#svn.branchmerge.advanced.advancedsyntax" title="Merge Syntax: Full Disclosure">the section called “Merge Syntax: Full Disclosure”</a> later
      in this chapter), and take special care to keep track of what's
      already been merged and what hasn't.  For this reason,
      we <span class="emphasis"><em>strongly</em></span> recommend that you make sure your
      client and server are at least at version 1.5.</p>
      <div class="sidebar" title="Merge Tracking">
        <a id="svn.branchmerge.basicmerging.mergetracking"></a>
        <div class="titlepage">
          <div>
            <div>
              <p class="title">
                <strong>Merge Tracking</strong>
              </p>
            </div>
          </div>
        </div>
        <p>
        <a id="idp12179440" class="indexterm"></a>Subversion 1.5 introduced the
        <em class="firstterm">merge tracking</em> feature to Subversion.
        Prior to this feature keeping track of merges required cumbersome
        manual procedures or the use of external tools. Subsequent
        releases of Subversion introduced many enhancements and bug
        fixes to merge tracking, which is why we recommend using the
        most recent versions for both your server and client.  Keep in
        mind that even if your server is running 1.5-1.7, you can still
        use a 1.8 client.  This is particularly important with regard to merge
        tracking, because the overwhelming majority of fixes and enhancements
        to it are on the client side.</p>
      </div>
      <div class="sect2" title="Changesets">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.changesets"></a>Changesets</h3>
            </div>
          </div>
        </div>
        <p>
        <a id="idp12183648" class="indexterm"></a>Before we proceed further, we should warn you that there's
        a lot of discussion of <span class="quote">“<span class="quote">changes</span>”</span> in
        the pages ahead.  A lot of people experienced with version
        control systems use the terms <span class="quote">“<span class="quote">change</span>”</span>
        and <span class="quote">“<span class="quote">changeset</span>”</span> interchangeably, and we should
        clarify what Subversion understands as
        a <em class="firstterm">changeset</em>.</p>
        <p>Everyone seems to have a slightly different definition
        of changeset, or at least a different
        expectation of what it means for a version control system to
        have one.  For our purposes, let's say that a changeset is just
        a collection of changes with a unique name.  The changes might
        include textual edits to file contents, modifications to tree
        structure, or tweaks to metadata.  In more common speak, a
        changeset is just a patch with a name you can refer to.</p>
        <p>In Subversion, a global revision
        number <em class="replaceable"><code>N</code></em> names a tree in the
        repository: it's the way the repository looked after the
        <em class="replaceable"><code>N</code></em>th commit.  It's also the name of
        an implicit changeset: if you compare
        tree <em class="replaceable"><code>N</code></em> with
        tree <em class="replaceable"><code>N</code></em>-1, you can derive the exact
        patch that was committed.  For this reason, it's easy to think
        of revision <em class="replaceable"><code>N</code></em> as not just a tree,
        but a changeset as well.  If you use an issue tracker to
        manage bugs, you can use the revision numbers to refer to
        particular patches that fix bugs—for example,
        <span class="quote">“<span class="quote">this issue was fixed by r9238.</span>”</span> Somebody
        can then run <strong class="userinput"><code>svn log -r 9238</code></strong> to read about
        the exact changeset that fixed the bug, and run
        <strong class="userinput"><code>svn diff -c 9238</code></strong> to see the patch itself.
        And (as you'll see shortly)
        Subversion's <span class="command"><strong>svn merge</strong></span> command is able to use
        revision numbers.  You can merge specific changesets from one
        branch to another by naming them in the merge
        arguments: passing <strong class="userinput"><code>-c 9238</code></strong>
        to <span class="command"><strong>svn merge</strong></span> would merge changeset r9238
        into your working copy.</p>
      </div>
      <div class="sect2" title="Keeping a Branch in Sync">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.basicmerging.stayinsync"></a>Keeping a Branch in Sync</h3>
            </div>
          </div>
        </div>
        <p>
        <a id="idp12197184" class="indexterm"></a>
        <a id="idp12198672" class="indexterm"></a>Continuing with our running example, let's suppose
        that a week has passed since you started working on your
        private branch.  Your new feature isn't finished yet, but at
        the same time you know that other people on your team continue
        to make important changes in the
        project's <code class="filename">/trunk</code>.  It's in your best
        interest to replicate those changes to your own branch, just
        to make sure they mesh well with your changes.  This is done
        by performing an <em class="firstterm">automatic sync merge</em>—a
        merge operation designed to bring your branch up to date with
        any changes made to its ancestral parent branch since your
        branch was created.
        <a id="idp12202416" class="indexterm"></a> An <span class="quote">“<span class="quote">automatic</span>”</span> merge is simply
        one in which you provide the bare minimum of information required
        for a merge (i.e. a single merge source and a working copy target)
        and let Subversion determine which changes need merging—no
        changesets are passed to <span class="command"><strong>svn merge</strong></span> via the
        <code class="option">-r</code> or <code class="option">-c</code> options in an automatic
        merge.</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>Frequently keeping your branch in sync with the main
          development line helps prevent <span class="quote">“<span class="quote">surprise</span>”</span>
          conflicts when the time comes for you to fold your changes
          back into the trunk.</p>
              </td>
            </tr>
          </table>
        </div>
        <p>Subversion is aware of the history of your branch and
        knows when it split away from the trunk.  To perform a sync
        merge, first make sure your working copy of the branch
        is <span class="quote">“<span class="quote">clean</span>”</span>—that it has no local
        modifications reported by <span class="command"><strong>svn status</strong></span>.  Then
        simply run:</p>
        <div class="informalexample">
          <pre class="screen">
$ pwd
/home/user/my-calc-branch

$ svn merge ^/calc/trunk
--- Merging r341 through r351 into '.':
U    doc/INSTALL
U    src/real.c
U    src/button.c
U    Makefile
--- Recording mergeinfo for merge of r341 through r351 into '.':
 U   .
 $
</pre>
        </div>
        <p>
        <a id="idp12211008" class="indexterm"></a>This basic syntax—<strong class="userinput"><code>svn merge
        <em class="replaceable"><code>URL</code></em></code></strong>—tells
        Subversion to merge all changes which have not been previously
        merged from the URL to the current working directory (which is
        typically the root of your working copy).  Notice that we're
        using the caret (<code class="literal">^</code>)
        syntax<sup>[<a id="idp12214416" href="#ftn.idp12214416" class="footnote">33</a>]</sup> to avoid having to type out the
        entire <code class="filename">/trunk</code> URL.  Also note
        the <span class="quote">“<span class="quote">Recording mergeinfo for merge…</span>”</span>
        notification.  This tells you that the merge is updating
        the <code class="literal">svn:mergeinfo</code> property. We'll discuss
        both this property and these notifications later in this
        chapter, in
        <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.mergeinfo" title="Mergeinfo and Previews">the section called “Mergeinfo and Previews”</a>.</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="idp12218480" class="indexterm"></a>In this book and elsewhere (Subversion mailing
          lists, articles on merge tracking, etc.) you will frequently
          come across the term <em class="firstterm">mergeinfo</em>. This
          is simply shorthand for the <code class="literal">svn:mergeinfo</code>
          property.</p>
              </td>
            </tr>
          </table>
        </div>
        <div class="sidebar" title="Keeping a Branch in Sync Without Merge Tracking">
          <div class="titlepage">
            <div>
              <div>
                <p class="title">
                  <strong>Keeping a Branch in Sync Without Merge Tracking</strong>
                </p>
              </div>
            </div>
          </div>
          <p>You may not always be able to use Subversion's merge
          tracking feature, perhaps because your server is running
          Subversion 1.4 or earlier or you must use an older client.
          In such a scenario, you can of course still perform merges,
          but Subversion will need you to manually do many of the historical
          calculations that it automatically does on your behalf when the
          merge tracking feature is available.</p>
          <p>To replicate the most recent trunk changes you need to
          perform sync merges the <span class="quote">“<span class="quote">old-fashioned</span>”</span>
          way—by specifying ranges of revisions you wish to
          merge.</p>
          <p>Using the ongoing example, you know that you branched
          <code class="filename">/calc/trunk</code> to 
          <code class="filename">/calc/branches/my-calc-branch</code> in revision
          341:</p>
          <div class="informalexample">
            <pre class="screen">
$ svn log -v -r341
------------------------------------------------------------------------
r341 | user | 2013-02-15 07:41:25 -0500 (Fri, 15 Feb 2013) | 1 line
Changed paths:
   A /calc/branches/my-calc-branch (from /calc/trunk:340)

Creating a private branch of /calc/trunk.
------------------------------------------------------------------------
</pre>
          </div>
          <p>When you are ready to synchronize your branch with the
          ongoing changes from trunk, you specify the starting
          revision as the revision of <code class="filename">/calc/trunk</code>
          which the branch was copied from and the ending revision as
          the youngest change on <code class="filename">/calc/trunk</code>.  You
          can find the latter with the <span class="command"><strong>svn log</strong></span> command
          with the <code class="option">-r</code> set to <code class="literal">HEAD</code>:</p>
          <div class="informalexample">
            <pre class="screen">
$ svn log -q -rHEAD http://svn.example.com/repos/calc/trunk
------------------------------------------------------------------------
r351 | sally | 2013-02-16 08:04:22 -0500 (Sat, 16 Feb 2013)
------------------------------------------------------------------------

$ svn merge http://svn.example.com/repos/calc/trunk -r340:351
U    doc/INSTALL
U    src/real.c
U    src/button.c
U    Makefile
</pre>
          </div>
          <p>After any conflicts have been resolved, you can commit
          the merged changes to your branch.  Now, to avoid
          accidentally trying to merge these same changes into your
          branch again in the future, you'll need to record the fact
          that you've already merged them.  But where should that
          record be kept?  One of the simplest places to record this
          information is in the log message for the commit of the
          merge:</p>
          <div class="informalexample">
            <pre class="screen">
$ svn ci -m "Sync the my-calc-branch with ^/calc/trunk through r351."
…
</pre>
          </div>
          <p>The next time you sync
          <code class="filename">/calc/branches/my-calc-branch</code>  with
          <code class="filename">/calc/trunk</code> you repeat this process, except
          that the starting revision is the <span class="emphasis"><em>youngest</em></span>
          revision that's already been merged in from the trunk.
          If you've been keeping good records of your merges in the
          commit log messages, you should be able to determine what
          that youngest revision was by reading the revision logs
          associated with your branch.  Once you know your starting
          revision, you can perform another sync merge:</p>
          <div class="informalexample">
            <pre class="screen">
$ svn log -q -rHEAD http://svn.example.com/repos/calc/trunk
------------------------------------------------------------------------
r959 | sally | 2013-03-5 7:30:21 -0500 (Tue, 05 Mar 2013)
------------------------------------------------------------------------

$ svn merge http://svn.example.com/repos/calc/trunk -r351:959
…
</pre>
          </div>
        </div>
        <p>After running the prior example, your branch working copy
        now contains new local modifications, and these edits are
        duplications of all of the changes that have happened on the
        trunk since you first created your branch:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn status
 M      .
M       Makefile
M       doc/INSTALL
M       src/button.c
M       src/real.c
</pre>
        </div>
        <p>At this point, the wise thing to do is look at the changes
        carefully with <span class="command"><strong>svn diff</strong></span>, and then build and
        test your branch.  Notice that the current working directory
        (<span class="quote">“<span class="quote"><code class="filename">.</code></span>”</span>) has also been
        modified; <span class="command"><strong>svn diff</strong></span> shows that
        its <code class="literal">svn:mergeinfo</code> property has been created.
        </p>
        <div class="informalexample">
          <pre class="screen">
$ svn diff --depth empty .
Index: .
===================================================================
--- .   (revision 351)
+++ .   (working copy)

Property changes on: .
___________________________________________________________________
Added: svn:mergeinfo
   Merged /calc/trunk:r341-351
</pre>
        </div>
        <p>
        This new property is important merge-related metadata
        that you should <span class="emphasis"><em>not</em></span> touch, since it is
        needed by future <span class="command"><strong>svn merge</strong></span> commands.
        (We'll learn more about this metadata later in the
        chapter.)</p>
        <p>After performing the merge, you might also need to resolve
        some conflicts—just as you do with <span class="command"><strong>svn
        update</strong></span>—or possibly make some small edits to get
        things working properly.  (Remember, just because there are
        no <span class="emphasis"><em>syntactic</em></span> conflicts doesn't mean there
        aren't any <span class="emphasis"><em>semantic</em></span> conflicts!)  If you
        encounter serious problems, you can always abort the local
        changes by running <strong class="userinput"><code>svn revert . -R</code></strong> (which
        will undo all local modifications) and starting a
        long <span class="quote">“<span class="quote">what's going on?</span>”</span> discussion with your
        collaborators.  If things look good, however, you can
        submit these changes into the repository:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn commit -m "Sync latest trunk changes to my-calc-branch."
Sending        .
Sending        Makefile
Sending        doc/INSTALL
Sending        src/button.c
Sending        src/real.c
Transmitting file data ....
Committed revision 352.
</pre>
        </div>
        <p>At this point, your private branch is now <span class="quote">“<span class="quote">in
        sync</span>”</span> with the trunk, so you can rest easier knowing
        that as you continue to work in isolation, you're not drifting
        too far away from what everyone else is doing.</p>
        <div class="sidebar" title="Why Not Use Patches Instead?">
          <div class="titlepage">
            <div>
              <div>
                <p class="title">
                  <strong>Why Not Use Patches Instead?</strong>
                </p>
              </div>
            </div>
          </div>
          <p>A question may be on your mind, especially if you're a
          Unix user: why bother to use <span class="command"><strong>svn merge</strong></span> at
          all?  Why not simply use <span class="command"><strong>svn patch</strong></span> or the
          operating system's <span class="command"><strong>patch</strong></span> command to
          accomplish the same job?  For example:</p>
          <div class="informalexample">
            <pre class="screen">
$ cd my-calc-branch

$ svn diff -r 341:351 ^/calc/trunk &gt; my-patch-file

$ svn patch my-patch-file
U         doc/INSTALL
U         src/real.c
U         src/button.c
U         Makefile
</pre>
          </div>
          <p>In this particular example, there really isn't much
          difference.  But <span class="command"><strong>svn merge</strong></span> has special
          abilities that surpass the <span class="command"><strong>patch</strong></span> program.
          The file format used by <span class="command"><strong>patch</strong></span> is quite
          limited; it's able to tweak file contents only.  There's no
          way to represent changes to <span class="emphasis"><em>trees</em></span>, such
          as the addition, removal, or renaming of files and
          directories.  Nor can the <span class="command"><strong>patch</strong></span> program
          notice changes to properties.  If Sally's change had,
          say, added a new directory, the output of <span class="command"><strong>svn
          diff</strong></span> wouldn't have mentioned it at
          all.  <span class="command"><strong>svn diff</strong></span> outputs only the limited
          patch format, so there are some ideas it simply can't
          express.  Even Subversion's own <span class="command"><strong>svn patch</strong></span>
          subcommand, while more flexible than the patch program, still has
          similar limitations.</p>
          <p>The <span class="command"><strong>svn merge</strong></span> command, however, can
          express changes in tree structure and properties by directly
          applying them to your working copy.  Even more important,
          this command records the changes that have been duplicated
          to your branch so that Subversion is aware of exactly which
          changes exist in each location (see
          <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.mergeinfo" title="Mergeinfo and Previews">the section called “Mergeinfo and Previews”</a>).
          This is a critical feature that makes branch management
          usable; without it, users would have to manually keep notes
          on which sets of changes have or haven't been merged
          yet.</p>
        </div>
        <p>Suppose that another week has passed.  You've committed
        more changes to your branch, and your comrades have continued
        to improve the trunk as well.  Once again, you want to
        replicate the latest trunk changes to your branch and bring
        yourself in sync.  Just run the same merge command
        again!</p>
        <div class="informalexample">
          <pre class="screen">
$ svn merge ^/calc/trunk
svn: E195020: Cannot merge into mixed-revision working copy [352:357]; try up\
dating first
$
</pre>
        </div>
        <p>Well that was unexpected!  After making changes to your
        branch over the past week you now find yourself with a working
        copy that contains a mixture of revisions (see
        <a class="xref" href="svn.basic.in-action.html#svn.basic.in-action.mixedrevs" title="Mixed-revision working copies">the section called “Mixed-revision working copies”</a>).  With Subversion
        1.7 and later, the <span class="command"><strong>svn merge</strong></span>
        subcommand disables merges into mixed-revision working copies
        by default.  Without going into too much detail, this is
        because of limitations in the way merges are tracked by the
        <code class="literal">svn:mergeinfo</code> property (see
        <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.mergeinfo" title="Mergeinfo and Previews">the section called “Mergeinfo and Previews”</a> for
        details).  These limitations mean that merges into
        mixed-revision working copies can result in unexpected text
        and tree conflicts.<sup>[<a id="idp12280928" href="#ftn.idp12280928" class="footnote">34</a>]</sup>  We don't want any needless conflicts, so
        we update the working copy and then reattempt the
        merge.</p>
        <div class="informalexample">
          <pre class="screen">
$ svn up
Updating '.':
At revision 361.

$ svn merge ^/calc/trunk
--- Merging r352 through r361 into '.':
U    src/real.c
U    src/main.c
--- Recording mergeinfo for merge of r352 through r361 into '.':
 U   .
</pre>
        </div>
        <p>Subversion knows which trunk changes you previously
        replicated to your branch, so it carefully replicates only
        those changes you don't yet have.  And once again, you build,
        test, and <span class="command"><strong>svn commit</strong></span> the local modifications
        to your branch.</p>
        <div class="sidebar" title="Subtree Merges and Subtree Mergeinfo">
          <a id="svn.branchmerge.basicmerging.stayinsync.subtree"></a>
          <div class="titlepage">
            <div>
              <div>
                <p class="title">
                  <strong>Subtree Merges and Subtree Mergeinfo</strong>
                </p>
              </div>
            </div>
          </div>
          <p>
          <a id="idp12287184" class="indexterm"></a>
          <a id="idp12288672" class="indexterm"></a>In most of the examples in this chapter the
          merge target is the root directory of a branch (see
          <a class="xref" href="svn.branchmerge.whatis.html" title="What's a Branch?">the section called “What's a Branch?”</a>). While this is a
          best practice, you may occasionally need to merge directly
          to some child of the branch root. This type of merge is
          called a <em class="firstterm">subtree merge</em> and the
          mergeinfo recorded to describe it is called
          <em class="firstterm">subtree mergeinfo</em>. There is nothing
          special about subtree merges or subtree mergeinfo.  In fact
          there is really only one important point to keep in mind
          about these concepts: the complete record of merges to a
          branch may not be contained solely in the mergeinfo on the
          branch root.  You may have to consider subtree mergeinfo
          to get a full accounting.  Fortunately Subversion does this
          for you and rarely will you need to concern yourself with
          it.  A brief example will help explain:</p>
          <div class="informalexample">
            <pre class="screen">
# We need to merge r958 from trunk to branches/proj-X/doc/INSTALL,
# but that revision also affects main.c, which we don't want to merge:
$ svn log --verbose --quiet -r 958 ^/
------------------------------------------------------------------------
r958 | bruce | 2011-10-20 13:28:11 -0400 (Thu, 20 Oct 2011)
Changed paths:
   M /trunk/doc/INSTALL
   M /trunk/src/main.c
------------------------------------------------------------------------

# No problem, we'll do a subtree merge targeting the INSTALL file
# directly, but first take a note of what mergeinfo exists on the
# root of the branch:
$ cd branches/proj-X

$ svn propget svn:mergeinfo --recursive
Properties on '.':
  svn:mergeinfo
    /trunk:651-652

# Now we perform the subtree merge, note that merge source
# and target both point to INSTALL:
$ svn merge ^/trunk/doc/INSTALL doc/INSTALL -c 958
--- Merging r958 into 'doc/INSTALL':
U    doc/INSTALL
--- Recording mergeinfo for merge of r958 into 'doc/INSTALL':
 G   doc/INSTALL

# Once the merge is complete there is now subtree mergeinfo on INSTALL:
$ svn propget svn:mergeinfo --recursive
Properties on '.':
  svn:mergeinfo
    /trunk:651-652
Properties on 'doc/INSTALL':
  svn:mergeinfo
    /trunk/doc/INSTALL:651-652,958

# What if we then decide we do want all of r958? Easy, all we need do is
# repeat the merge of that revision, but this time to the root of the
# branch, Subversion notices the subtree mergeinfo on INSTALL and doesn't
# try to merge any changes to it, only the changes to main.c are merged:
$ svn merge ^/subversion/trunk . -c 958
--- Merging r958 into '.':
U    src/main.c
--- Recording mergeinfo for merge of r958 into '.':
 U   .
--- Eliding mergeinfo from 'doc/INSTALL':
 U   doc/INSTALL
</pre>
          </div>
          <p>
          <a id="idp12295840" class="indexterm"></a>You might be wondering
          why <code class="filename">INSTALL</code> in the above example has
          mergeinfo for r651-652, when we only merged r958. This is
          due to mergeinfo inheritance, which we'll cover in the
          sidebar
          <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.mergeinfo.inheritance" title="Mergeinfo Inheritance">Mergeinfo Inheritance</a>.  Also note that the subtree mergeinfo on
          <code class="filename">doc/INSTALL</code> was removed, or
          <span class="quote">“<span class="quote">elided</span>”</span>.  This is called
          <em class="firstterm">mergeinfo elision</em> and it occurs
          whenever Subversion detects redundant subtree mergeinfo.</p>
        </div>
        <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>Prior to Subversion 1.7, merges unconditionally updated
          <span class="emphasis"><em>all</em></span> of the subtree mergeinfo under the
          target to describe the merge. For users with a lot of subtree
          mergeinfo this meant that relatively <span class="quote">“<span class="quote">simple</span>”</span>
          merges (e.g. one which applied a diff to only a single file)
          resulted in changes to every subtree with mergeinfo, even
          those that were not parents of the affected path(s). This
          caused some level of confusion and frustration. Subversion 1.7
          and later addresses this problem by only updating the mergeinfo
          on subtrees which are parents of the paths modified by the merge
          (i.e. paths changed, added, or deleted by application of the
          difference, see
          <a class="xref" href="svn.branchmerge.advanced.html#svn.branchmerge.advanced.advancedsyntax" title="Merge Syntax: Full Disclosure">the section called “Merge Syntax: Full Disclosure”</a>).
          The one exception to this behavior regards the actual merge
          target; the merge target's mergeinfo is always updated to
          describe the merge, even if the applied difference made no
          changes.</p>
              </td>
            </tr>
          </table>
        </div>
      </div>
      <div class="sect2" title="Reintegrating a Branch">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.basicmerging.reintegrate"></a>Reintegrating a Branch</h3>
            </div>
          </div>
        </div>
        <p>What happens when you finally finish your work, though?
        Your new feature is done, and you're ready to merge your
        branch changes back to the trunk (so your team can enjoy the
        bounty of your labor).  The process is simple.  First, bring
        your branch into sync with the trunk again, just as you've been
        doing all along<sup>[<a id="idp12306784" href="#ftn.idp12306784" class="footnote">35</a>]</sup>:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn up # (make sure the working copy is up to date)
Updating '.':
At revision 378.

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

$ # build, test, ...

$ svn commit -m "Final merge of trunk changes to my-calc-branch."
Sending        .
Sending        src/main.c
Transmitting file data .
Committed revision 379.
</pre>
        </div>
        <p>Now, use <span class="command"><strong>svn merge</strong></span> subcommand to automatically
        replicate your branch changes back into the trunk.  This type of
        merge is called an
        <a id="idp12310864" class="indexterm"></a> <span class="quote">“<span class="quote">automatic reintegrate</span>”</span> merge.  You'll need
        a working copy of <code class="filename">/calc/trunk</code>.  You can get one
        by doing an <span class="command"><strong>svn checkout</strong></span>, dredging up an old trunk
        working copy from somewhere on your disk, or
        using <span class="command"><strong>svn switch</strong></span> (see
        <a class="xref" href="svn.branchmerge.switchwc.html" title="Traversing Branches">the section called “Traversing Branches”</a>).</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>The term <span class="quote">“<span class="quote">reintegrating</span>”</span> comes from the
          <span class="command"><strong>merge</strong></span> option <code class="option">--reintegrate</code>.
          This option is deprecated in Subversion 1.8 (which automatically
          detects when a reintegrate merge is needed), but is required
          for Subversion 1.5 through 1.7 clients when performing reintegrate
          merges.</p>
              </td>
            </tr>
          </table>
        </div>
        <p>Your trunk working copy cannot have any local edits, switched
        paths, or contain a mixture of revisions (see
        <a class="xref" href="svn.basic.in-action.html#svn.basic.in-action.mixedrevs" title="Mixed-revision working copies">the section called “Mixed-revision working copies”</a>).  While
        these are typically best practices for merging anyway, they
        are <span class="emphasis"><em>required</em></span> for automatic reintegrate
        merges.</p>
        <p>Once you have a clean working copy of the trunk, you're
        ready to merge your branch back into it:</p>
        <div class="informalexample">
          <pre class="screen">
$ pwd
/home/user/calc-trunk

$ svn update
Updating '.':
At revision 379.

$ svn merge ^/calc/branches/my-calc-branch
--- Merging differences between repository URLs into '.':
U    src/real.c
U    src/main.c
U    Makefile
--- Recording mergeinfo for merge between repository URLs into '.':
 U   .

$ # build, test, verify, ...

$ svn commit -m "Merge my-calc-branch back into trunk!"
Sending        .
Sending        Makefile
Sending        src/main.c
Sending        src/real.c
Transmitting file data ...
Committed revision 380.
</pre>
        </div>
        <p>Congratulations, your branch-specific changes have now
        been merged back into the main line of development.  Notice that
        the automatic reintegrate merge did a different sort of work than
        what you've done up until now.  Previously, we were
        asking <span class="command"><strong>svn merge</strong></span> to grab the <span class="quote">“<span class="quote">next
        set</span>”</span> of changes from one line of development (the
        trunk) and duplicate them to another (your branch).  This is
        fairly straightforward, and each time Subversion knows how to
        pick up where it left off.  In our prior examples, you can see
        that first it merges the ranges 341:351 from
        <code class="filename">/calc/trunk</code> to
        <code class="filename">/calc/branches/my-calc-branch</code>;
        later on, it continues by merging the next contiguously
        available range, 351:361.  When doing the final sync, it
        merges the range 361:378.</p>
        <p>When merging <code class="filename">/calc/branches/my-calc-branch</code>
        back to the <code class="filename">/calc/trunk</code>, however, the
        underlying mathematics are quite different.  Your feature
        branch is now a mishmash of both duplicated trunk changes and
        private branch changes, so there's no simple contiguous range
        of revisions to copy over.  By using an automatic merge, you're
        asking Subversion to carefully replicate <span class="emphasis"><em>only</em></span>
        those changes unique to your branch.  (And in fact, it does
        this by comparing the latest trunk tree with the latest branch
        tree:  the resulting difference is exactly your branch
        changes!)</p>
        <p>Keep in mind that the automatic reintegrate merges only support
        the use case described above.  Because of this narrow focus, in
        addition to the requirements previously mentioned (up-to-date working
        copy <sup>[<a id="idp12329456" href="#ftn.idp12329456" class="footnote">36</a>]</sup>
        with no mixed-revisions, switched paths or local changes) it will not
        function in combination with most of the other
        <span class="command"><strong>svn merge</strong></span> options. You'll get an error if you
        use any non-global options but these: <code class="option">--accept</code>,
        <code class="option">--dry-run</code>, <code class="option">--diff3-cmd</code>,
        <code class="option">--extensions</code>, or <code class="option">--quiet</code>.</p>
        <p>Now that your private branch is merged to trunk, you may
        wish to remove it from the repository:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn delete ^/calc/branches/my-calc-branch \
             -m "Remove my-calc-branch, reintegrated with trunk in r381."
…
</pre>
        </div>
        <p>But wait!  Isn't the history of that branch valuable?
        What if somebody wants to audit the evolution of your feature
        someday and look at all of your branch changes?  No need to
        worry.  Remember that even though your branch is no longer
        visible in the <code class="filename">/calc/branches</code> directory, its
        existence is still an immutable part of the repository's
        history.  A simple <span class="command"><strong>svn log</strong></span> command on
        the <code class="filename">/calc/branches</code> URL will show the entire
        history of your branch.  Your branch can even be resurrected
        at some point, should you desire (see
        <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.resurrect" title="Resurrecting Deleted Items">the section called “Resurrecting Deleted Items”</a>).</p>
        <p>If you choose not to delete your branch after reintegrating
        it to the trunk you may continue to perform sync merges from the
        trunk and then reintegrate the branch again<sup>[<a id="idp12341040" href="#ftn.idp12341040" class="footnote">37</a>]</sup>. If you do this, only the changes made on your
        branch after the first reintegrate are merged to the trunk.</p>
      </div>
      <div class="sect2" title="Mergeinfo and Previews">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.basicmerging.mergeinfo"></a>Mergeinfo and Previews</h3>
            </div>
          </div>
        </div>
        <p>The basic mechanism Subversion uses to track
        changesets—that is, which changes have been merged to
        which branches—is by recording data in versioned
        properties.  Specifically, merge data is tracked in
        the <code class="literal">svn:mergeinfo</code> property attached to
        files and directories.  (If you're not familiar with
        Subversion properties, see <a class="xref" href="svn.advanced.props.html" title="Properties">the section called “Properties”</a>.)</p>
        <p>You can examine the mergeinfo property, just like any other
        versioned property:</p>
        <div class="informalexample">
          <pre class="screen">
$ cd my-calc-branch

$ svn pg svn:mergeinfo -v
Properties on '.':
  svn:mergeinfo
    /calc/trunk:341-378
</pre>
        </div>
        <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>While it is possible to
          modify <code class="literal">svn:mergeinfo</code> just as you might
          any other versioned property, we strongly discourage doing
          so unless you <span class="emphasis"><em>really</em></span> know what you're
          doing.</p>
              </td>
            </tr>
          </table>
        </div>
        <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>The amount of <code class="literal">svn:mergeinfo</code> on a single
          path can get quite large, as can the output of a
          <span class="command"><strong>svn propget --recursive</strong></span> or
          <span class="command"><strong>svn proplist --recursive</strong></span> when dealing with
          large amounts of subtree mergeinfo. 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>
          . The formatted output produced by the
          <code class="option">--verbose</code> option with either of these
          subcommands is often very helpful in these cases.</p>
              </td>
            </tr>
          </table>
        </div>
        <p>The <code class="literal">svn:mergeinfo</code> property is
        automatically maintained by Subversion whenever you
        run <span class="command"><strong>svn merge</strong></span>.  Its value indicates which
        changes made to a given path have been replicated into the
        directory in question.  In our previous example, the path
        which is the source of the merged changes is
        <code class="filename">/calc/trunk</code> and the directory which has
        received the changes is
        <code class="filename">/calc/branches/my-calc-branch</code>.
        Earlier versions of Subversion maintained the
        <code class="literal">svn:mergeinfo</code> property silently. You could
        still detect the changes, after a merge completed, with the
        <span class="command"><strong>svn diff</strong></span> or <span class="command"><strong>svn status</strong></span>
        subcommands, but the merge itself gave no indication when it
        changed the <code class="literal">svn:mergeinfo</code> property. In
        Subversion 1.7 and later this is no longer true as there are
        several notifications to alert you when a merge updates the
        <code class="literal">svn:mergeinfo</code> property. These notifications
        all begin with <span class="quote">“<span class="quote">--- Recording mergeinfo for</span>”</span>
        and appear at the end of the merge.  Unlike other merge
        notifications, these don't describe the application of a
        difference to a working copy
        (see <a class="xref" href="svn.branchmerge.advanced.html#svn.branchmerge.advanced.advancedsyntax" title="Merge Syntax: Full Disclosure">the section called “Merge Syntax: Full Disclosure”</a>),
        but instead describe "housekeeping" changes made to keep
        track of what was merged.</p>
        <p>Subversion also provides a subcommand, <span class="command"><strong>svn
        mergeinfo</strong></span>, which is helpful in seeing the merge
        relationships between two branches; specifically which changesets
        a directory has absorbed or which changesets it's still eligible
        to receive.  The latter gives a sort of preview of which changes a
        subsequent <span class="command"><strong>svn merge</strong></span> operation would replicate
        to your branch.  By default, <span class="command"><strong>svn mergeinfo</strong></span> gives
        an graphical overview of the relationship between to branches.
        Returning to our earlier example, we use the subcommand to analyze
        the relationship between <code class="filename">/calc/trunk</code> and
        <code class="filename">/calc/branches/my-calc-branch</code>:</p>
        <div class="informalexample">
          <pre class="screen">
$ cd my-calc-branch

$ svn mergeinfo ^/calc/trunk
    youngest common ancestor
    |         last full merge
    |         |        tip of branch
    |         |        |         repository path

    340                382
    |                  |
  -------| |------------         calc/trunk
     \          /
      \        /
       --| |------------         calc/branches/my-calc-branch
              |        |
              379      382
</pre>
        </div>
        <p>The diagram shows that <code class="filename">/calc/branches/my-calc-branch
      </code> was copied from <code class="filename">/calc/trunk@340</code> and
      that most recent automatic merge was the reintegrate merge we made
      from the branch to the trunk in r380.  Notice that the diagram does
      <span class="emphasis"><em>not</em></span> show the four automatic sync merges we made
      in revisions 352, 362, 372, and 379.  Only the most recent automatic
      merge, in either direction<sup>[<a id="idp12371936" href="#ftn.idp12371936" class="footnote">38</a>]</sup>, is shown.  This
      default output is useful for obtaining an overview of the merges
      between two branches, but to see the specific revisions which were
      merged we use the <code class="option">--show-revs=merged</code> option:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn mergeinfo ^/calc/trunk --show-revs merged
r344
r345
r346
…
r366
r367
r368
</pre>
        </div>
        <p>Likewise, to see which changes are eligible to merge from the
        trunk to the branch we can use the <code class="option">--show-revs=eligible
        </code> option:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn mergeinfo ^/calc/trunk --show-revs eligible
r380
r381
r382
</pre>
        </div>
        <div class="sidebar" title="Operative and Inoperative Merge Revisions">
          <a id="svn.branchmerge.basicmerging.mergeinfo.operativerevs"></a>
          <div class="titlepage">
            <div>
              <div>
                <p class="title">
                  <strong>Operative and Inoperative Merge Revisions</strong>
                </p>
              </div>
            </div>
          </div>
          <p>The revision lists produced by the <code class="option">--show-revs
          </code> option include only revisions which made (or would make)
          changes when merged.  So while we have merged a contiguous range of
          revisions (i.e. r341-378) from <code class="filename">/calc/trunk</code> to
          <code class="filename">/calc/branches/my-calc-branch</code>, only the
          revisions listed with the <code class="option">--show-revs=merged</code> option
          actually represent changes made on <code class="filename">/calc/trunk</code>.
          These revisions are described as <span class="quote">“<span class="quote">operative</span>”</span>
          revisions as regards merging, not to be confused with the
          operative revision used with the <code class="option">-r</code> option, see
          <a class="xref" href="svn.advanced.pegrevs.html" title="Peg and Operative Revisions">the section called “Peg and Operative Revisions”</a>.  Not suprisingly, the
          revisions in the range r341-378 that are <span class="emphasis"><em>not</em></span>
          listed as merged are termed <span class="quote">“<span class="quote">inoperative</span>”</span> revisions.
        </p>
        </div>
        <p>The <span class="command"><strong>svn mergeinfo</strong></span> command requires
        a <span class="quote">“<span class="quote">source</span>”</span> URL (where the changes come
        from), and takes an optional <span class="quote">“<span class="quote">target</span>”</span> URL (where
        the changes merge to).  If no target URL is given,
        it assumes that the current working directory is the
        target.  In the prior example, because we're querying our
        branch working copy, the command assumes we're interested in
        receiving changes to <code class="filename">/calc/branches/my-calc-branch
        </code> from the specified trunk URL.</p>
        <p>Since Subversion 1.7, the
        <span class="command"><strong>svn mergeinfo</strong></span> subcommand can also account for
        subtree mergeinfo and non-inheritable mergeinfo.  It accounts for
        subtree mergeinfo by use of the <code class="option">--recursive</code> or
        <code class="option">--depth</code> options, while non-inheritable mergeinfo
        is considered by default.</p>
        <div class="sidebar" title="Mergeinfo Inheritance">
          <a id="svn.branchmerge.basicmerging.mergeinfo.inheritance"></a>
          <div class="titlepage">
            <div>
              <div>
                <p class="title">
                  <strong>Mergeinfo Inheritance</strong>
                </p>
              </div>
            </div>
          </div>
          <p>
          <a id="idp12391568" class="indexterm"></a>
          <a id="idp12393056" class="indexterm"></a>When a path has
          the <code class="literal">svn:mergeinfo</code> property set on it we
          say it has <em class="firstterm">explicit mergeinfo</em>.  This
          explicit mergeinfo describes not only what changes were
          merged into that particular directory, but also all the
          children of that directory (because those children inherit
          the mergeinfo of their parent path).  For example:</p>
          <div class="informalexample">
            <pre class="screen">
# What explicit mergeinfo exists on a branch?
$ svn propget svn:mergeinfo ^/branches/proj-X --recursive
/trunk:651-652

# What children does proj-X have?
$ svn list --recursive ^/branches/proj-X
doc/
doc/INSTALL
README
src/main.c

# Ask what revs were merged to a file with no explicit mergeinfo
$ svn mergeinfo ^/trunk/src/main.c ^/branches/proj-X/src/main.c \
                --show-revs merged
651
652
</pre>
          </div>
          <p>Notice from our first subcommand that only the root of
          <code class="filename">/branches/proj-X</code> has any explicit
          mergeinfo.  However, when we use
          <span class="command"><strong>svn mergeinfo</strong></span> to ask what was merged to
          <code class="filename">/branches/proj-X/src/main.c</code> it reports
          that the two revisions described in the explicit mergeinfo
          on <code class="filename">/branches/proj-X</code> were merged.  This is
          because <code class="filename">/branches/proj-X/src/main.c</code>, having
          no explicit mergeinfo of its own, inherits the mergeinfo from
          its nearest parent with explicit mergeinfo,
          <code class="filename">/branches/proj-X</code>.</p>
          <p>There are two cases in which mergeinfo is not inherited.
          First, if a path has explicit mergeinfo, then it never inherits
          mergeinfo. Another way to think of this is that explicit
          mergeinfo is always a complete record of the merges to a given
          path. Once it exists it overrides any mergeinfo that path might
          otherwise inherit. The second way is when dealing with
          non-inheritable mergeinfo, a special type of explicit mergeinfo
          that applies <span class="emphasis"><em>only</em></span> to the directory on which
          the <code class="literal">svn:mergeinfo</code> property is set (and it's
          only directories, non-inheritable mergeinfo is never set on
          files). For example:</p>
          <div class="informalexample">
            <pre class="screen">
# The '*' decorator indicates non-inheritable mergeinfo
$ svn propget svn:mergeinfo ^/branches/proj-X
/trunk:651-652,758*

# Revision 758 is non-inheritable, but still applies to the path it is
# set on. Here the '*' decorator signals that r758 is only partially
# merged from trunk. 
$ svn mergeinfo ^/trunk ^/branches/proj-X --show-revs merged
651
652
758*

# Revision 758 is not reported as merged because it is non-inheritable
# and applies only to ^/trunk
$ svn mergeinfo ^/trunk/src/main.c ^/branches/proj-X/src/main.c \
                --show-revs merged
651
652
</pre>
          </div>
          <p>You might never have to think about mergeinfo inheritance
          or encounter non-inheritable mergeinfo in your own repository.
          A discussion of the full ramifications of mergeinfo inheritance
          are beyond the scope of this book.  If you have more questions
          check out some of the references mentioned in
          <a class="xref" href="svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword" title="The Final Word on Merge Tracking">the section called “The Final Word on Merge Tracking”</a></p>
        </div>
        <p>Let's say we have a branch with both subtree and
        non-inheritable mergeinfo:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn pg svn:mergeinfo -vR
# Non-inheritable mergeinfo
Properties on '.':
  svn:mergeinfo
    /calc/trunk:354,385-388*
# Subtree mergeinfo
Properties on 'Makefile':
  svn:mergeinfo
    /calc/trunk/Makefile:354,380
</pre>
        </div>
        <p>From the above mergeinfo we see that r385-388 has only been
        merged into the root of the branch, but not any of the root's
        children.  We also see that r380 has only been merged to
        <code class="filename">Makefile</code>.
        When we use <span class="command"><strong>svn mergeinfo</strong></span> with the
        <code class="option">--recursive</code> option to see what has been merged
        from <code class="filename">/calc/trunk</code> to this branch, we see three
        revisions are flagged with the <code class="literal">*</code> marker:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn mergeinfo -R --show-revs=merged ^/calc/trunk .
r354
r380*
r385
r386
r387*
r388*
</pre>
        </div>
        <p>The <code class="literal">*</code> indicates revisions that are only
        <span class="emphasis"><em>partially</em></span> merged to the target in question
        (the meaning is the same if we are checking for eligible
        revisions).  What this means in this example is that if we tried
        to merge r380, r387, or r388 from <code class="filename">^/trunk</code> then
        more changes would result. Likewise, because r354, r385 and r386 are
        <span class="emphasis"><em>not</em></span> flagged with a <code class="literal">*</code>,
        we know that re-merging those revisions would have no result.
        <sup>[<a id="idp12419072" href="#ftn.idp12419072" class="footnote">39</a>]</sup></p>
        <p>Another way to get a more precise preview of a merge
        operation is to use the <code class="option">--dry-run</code>
        option:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn merge ^/paint/trunk paint-feature-branch --dry-run
--- Merging r290 through r383 into 'paint-feature-branch':
U    paint-feature-branch/src/palettes.c
U    paint-feature-branch/src/brushes.c
U    paint-feature-branch/Makefile

$ svn status
#  nothing printed, working copy is still unchanged.
</pre>
        </div>
        <p>The <code class="option">--dry-run</code> option doesn't actually
        apply any local changes to the working copy.  It shows only
        status codes that <span class="emphasis"><em>would</em></span> be printed in a
        real merge.  It's useful for getting a <span class="quote">“<span class="quote">high-level</span>”</span>
        preview of the potential merge, for those times
        when running <span class="command"><strong>svn diff</strong></span> gives too much
        detail.</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>After performing a merge operation, but before
          committing the results of the merge, you can use
          <strong class="userinput"><code>svn diff --depth=empty <em class="replaceable"><code>
          /path/to/merge/target</code></em></code></strong> to see only the
          changes to the immediate target of your merge.  If your merge
          target was a directory, only property differences are displayed.
          This is a handy way to see the changes to the
          <code class="literal">svn:mergeinfo</code> property recorded by the
          merge operation, which will remind you about what you've
          just merged.</p>
              </td>
            </tr>
          </table>
        </div>
        <p>Of course, the best way to preview a merge operation is to
        just do it!  Remember, running <span class="command"><strong>svn merge</strong></span>
        isn't an inherently risky thing (unless you've made local
        modifications to your working copy—but we already
        stressed that you shouldn't merge into such an
        environment).  If you don't like the results of the merge,
        simply run <strong class="userinput"><code>svn revert . -R</code></strong> to revert
        the changes from your working copy and retry the command with
        different options.  The merge isn't final until you
        actually <span class="command"><strong>svn commit</strong></span> the results.</p>
      </div>
      <div class="sect2" title="Undoing Changes">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.basicmerging.undo"></a>Undoing Changes</h3>
            </div>
          </div>
        </div>
        <p>An extremely common use for <span class="command"><strong>svn merge</strong></span>
        is to roll back a change that has already been committed.
        Suppose you're working away happily on a working copy of
        <code class="filename">/calc/trunk</code>, and you discover that the
        change made back in revision 392, which changed
        several code files, is completely wrong.  It never
        should have been committed.  You can use <span class="command"><strong>svn
        merge</strong></span> to <span class="quote">“<span class="quote">undo</span>”</span> the change in your
        working copy, and then commit the local modification to the
        repository.  All you need to do is to specify a
        <span class="emphasis"><em>reverse</em></span> difference.  (You can do this by
        specifying <code class="option">--revision 392:391</code>, or by an
        equivalent <code class="option">--change -392</code>.)</p>
        <div class="informalexample">
          <pre class="screen">
$ svn merge ^/calc/trunk . -c-392
--- Reverse-merging r392 into '.':
U    src/real.c
U    src/main.c
U    src/button.c
U    src/integer.c
--- Recording mergeinfo for reverse merge of r392 into '.':
 U   .

$ svn st
M       src/button.c
M       src/integer.c
M       src/main.c
M       src/real.c

$ svn diff
…
# verify that the change is removed
…

$ svn commit -m "Undoing erroneous change committed in r392."
Sending        src/button.c
Sending        src/integer.c
Sending        src/main.c
Sending        src/real.c
Transmitting file data ....
Committed revision 399.
</pre>
        </div>
        <p>As we mentioned earlier, one way to think about a
        repository revision is as a specific changeset.  By using the
        <code class="option">-r</code> option, you can ask <span class="command"><strong>svn
        merge</strong></span> to apply a changeset, or a whole range of
        changesets, to your working copy.  In our case of undoing a
        change, we're asking <span class="command"><strong>svn merge</strong></span> to apply
        changeset r392 to our working copy
        <span class="emphasis"><em>backward</em></span>.</p>
        <p>Keep in mind that rolling back a change like this is just
        like any other <span class="command"><strong>svn merge</strong></span> operation, so you
        should use <span class="command"><strong>svn status</strong></span> and <span class="command"><strong>svn
        diff</strong></span> to confirm that your work is in the state you
        want it to be in, and then use <span class="command"><strong>svn commit</strong></span>
        to send the final version to the repository.  After
        committing, this particular changeset is no longer reflected
        in the <code class="literal">HEAD</code> revision.</p>
        <p>Again, you may be thinking: well, that really didn't undo
        the commit, did it?  The change still exists in revision 392.
        If somebody checks out a version of the
        <code class="filename">calc</code> project between revisions 392 and
        398, she'll still see the bad change, right?</p>
        <p>Yes, that's true.  When we talk about
        <span class="quote">“<span class="quote">removing</span>”</span> a change, we're really talking about
        removing it from the <code class="literal">HEAD</code> revision.  The
        original change still exists in the repository's history.  For
        most situations, this is good enough.  Most people are only
        interested in tracking the <code class="literal">HEAD</code> of a
        project anyway.  There are special cases, however, where you
        really might want to destroy all evidence of the commit.
        (Perhaps somebody accidentally committed a confidential
        document.)  This isn't so easy, it turns out, because
        Subversion was deliberately designed to never lose
        information.  Revisions are immutable trees that build upon
        one another.  Removing a revision from history would cause a
        domino effect, creating chaos in all subsequent revisions and
        possibly invalidating all working copies.<sup>[<a id="idp12450464" href="#ftn.idp12450464" class="footnote">40</a>]</sup></p>
      </div>
      <div class="sect2" title="Resurrecting Deleted Items">
        <div class="titlepage">
          <div>
            <div>
              <h3 class="title"><a id="svn.branchmerge.basicmerging.resurrect"></a>Resurrecting Deleted Items</h3>
            </div>
          </div>
        </div>
        <p>The great thing about version control systems is that
        information is never lost.  Even when you delete a file or
        directory, it may be gone from the <code class="literal">HEAD</code>
        revision, but the object still exists in earlier revisions.
        One of the most common questions new users ask is, <span class="quote">“<span class="quote">How
        do I get my old file or directory back?</span>”</span></p>
        <p>The first step is to define
        exactly <span class="emphasis"><em>which</em></span> item you're
        trying to resurrect.  Here's a useful metaphor: you can think
        of every object in the repository as existing in a sort of
        two-dimensional coordinate system.  The first coordinate is a
        particular revision tree, and the second coordinate is a path
        within that tree.  So every version of your file or directory
        is defined by a specific coordinate pair.  (Remember the
        <span class="quote">“<span class="quote">peg revision</span>”</span>
        syntax—foo.c@224—mentioned back in
        <a class="xref" href="svn.advanced.pegrevs.html" title="Peg and Operative Revisions">the section called “Peg and Operative Revisions”</a>.)</p>
        <p>First, you might need to use <span class="command"><strong>svn log</strong></span> to
        discover the exact coordinate pair you wish to resurrect.  A
        good strategy is to run <strong class="userinput"><code>svn log --verbose</code></strong>
        in a directory that used to contain your deleted item.  The
        <code class="option">--verbose</code> (<code class="option">-v</code>) option shows
        a list of all changed items in each revision; all you need to
        do is find the revision in which you deleted the file or
        directory.  You can do this visually, or by using another tool
        to examine the log output (via <span class="command"><strong>grep</strong></span>, or
        perhaps via an incremental search in an editor).  If you know that
        the item in question was recently deleted you might also use
        the <code class="option">--limit</code> option to keep the log output brief
        enough to examine manually.</p>
        <div class="informalexample">
          <pre class="screen">
$ cd calc/trunk

$ svn log -v --limit 3
------------------------------------------------------------------------
r401 | sally | 2013-02-19 23:15:44 -0500 (Tue, 19 Feb 2013) | 1 line
Changed paths:
   M /calc/trunk/src/main.c

Follow-up to r400: Fix typos in help text.
------------------------------------------------------------------------
r400 | bill | 2013-02-19 20:55:08 -0500 (Tue, 19 Feb 2013) | 4 lines
Changed paths:
   M /calc/trunk/src/main.c
   D /calc/trunk/src/real.c

* calc/trunk/src/main.c: Update help text.

* calc/trunk/src/real.c: Remove this file, none of the APIs
  implemented here are used anymore.
------------------------------------------------------------------------
r399 | sally | 2013-02-19 20:05:14 -0500 (Tue, 19 Feb 2013) | 1 line
Changed paths:
   M /calc/trunk/src/button.c
   M /calc/trunk/src/integer.c
   M /calc/trunk/src/main.c
   M /calc/trunk/src/real.c

Undoing erroneous change committed in r392.
------------------------------------------------------------------------
</pre>
        </div>
        <p>In the example, we're assuming that you're looking for a
        deleted file <code class="filename">real.c</code>.  By looking through
        the logs of a parent directory, you've spotted that this file
        was deleted in revision 400.  Therefore, the last version of
        the file to exist was in the revision right before that.
        Conclusion: you want to resurrect the path
        <code class="filename">/calc/trunk/real.c</code> from revision
        399.</p>
        <p>That was the hard part—the research.  Now that you
        know what you want to restore, you have two different
        choices.</p>
        <p>One option is to use <span class="command"><strong>svn merge</strong></span> to apply
        revision 400 <span class="quote">“<span class="quote">in reverse.</span>”</span> (We already
        discussed how to undo changes in
        <a class="xref" href="svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.undo" title="Undoing Changes">the section called “Undoing Changes”</a>.)  This
        would have the effect of re-adding <code class="filename">real.c</code>
        as a local modification.  The file would be scheduled for
        addition, and after a commit, the file would again exist
        in <code class="literal">HEAD</code>.</p>
        <p>In this particular example, however, this is probably not
        the best strategy.  Reverse-applying revision 400 would not
        only schedule <code class="filename">real.c</code> for addition, but
        the log message indicates that it would also undo certain
        changes to <code class="filename">main.c</code>, which you don't
        want.  Certainly, you could reverse-merge revision 400 and
        then <span class="command"><strong>svn revert</strong></span> the local modifications to
        <code class="filename">main.c</code>, but this technique doesn't
        scale well.  What if 90 files were changed in revision
        400?</p>
        <p>A second, more targeted strategy is not to use
        <span class="command"><strong>svn merge</strong></span> at all, but rather to use the
        <span class="command"><strong>svn copy</strong></span> command.  Simply copy the exact
        revision and path <span class="quote">“<span class="quote">coordinate pair</span>”</span> from the
        repository to your working copy:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn copy ^/calc/trunk/src/real.c@399 ./real.c
A         real.c

$ svn st
A  +    real.c

# Commit the resurrection.
…
</pre>
        </div>
        <p>The plus sign in the status output indicates that the item
        isn't merely scheduled for addition, but scheduled for
        addition <span class="quote">“<span class="quote">with history.</span>”</span>  Subversion remembers
        where it was copied from.  In the future, running <span class="command"><strong>svn
        log</strong></span> on this file will traverse back through the
        file's resurrection and through all the history it had prior
        to revision 399.  In other words, this new
        <code class="filename">real.c</code> isn't really new; it's a direct
        descendant of the original, deleted file.  This is usually
        considered a good and useful thing.  If, however, you wanted
        to resurrect the file <span class="emphasis"><em>without</em></span>
        maintaining a historical link to the old file, this technique
        works just as well:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn cat ^/calc/trunk/src/real.c@399 &gt; ./real.c

$ svn add real.c
A         real.c

# Commit the resurrection.
…
</pre>
        </div>
        <p>Although our example shows us resurrecting a file, note
        that these same techniques work just as well for resurrecting
        deleted directories.  Also note that a resurrection doesn't
        have to happen in your working copy—it can happen
        entirely in the repository:</p>
        <div class="informalexample">
          <pre class="screen">
$ svn copy ^/calc/trunk/src/real.c@399 ^/calc/trunk/src/real.c \
           -m "Resurrect real.c from revision 399."

Committed revision 402.

$ svn up
Updating '.':
A    real.c
Updated to revision 402.
</pre>
        </div>
      </div>
      <div class="footnotes">
        <br />
        <hr width="100" align="left" />
        <div class="footnote">
          <p><sup>[<a id="ftn.idp12214416" href="#idp12214416" class="para">33</a>] </sup>This was introduced in svn
        1.6.</p>
        </div>
        <div class="footnote">
          <p><sup>[<a id="ftn.idp12280928" href="#idp12280928" class="para">34</a>] </sup>The <span class="command"><strong>svn
        merge</strong></span> subcommand
        option <code class="option">--allow-mixed-revisions</code> allows you to
        override this prohibition, but you should only do so if you
        understand the ramifications and have a good reason for
        it.</p>
        </div>
        <div class="footnote">
          <p><sup>[<a id="ftn.idp12306784" href="#idp12306784" class="para">35</a>] </sup>Since Subversion 1.7 you don't
        absolutely have to do all your sync merges to the root of your
        branch as we do in this example.  <span class="emphasis"><em>If</em></span> your
        branch is effectively synced via a series of subtree
        merges then the reintegrate will work, but ask yourself, if the
        branch is effectively synced, then why are you doing subtree
        merges? Doing so is almost always needlessly
        complex.</p>
        </div>
        <div class="footnote">
          <p><sup>[<a id="ftn.idp12329456" href="#idp12329456" class="para">36</a>] </sup>Automatic reintegrate merges are allowed if the
        target is a shallow checkout
        (see <a class="xref" href="svn.advanced.sparsedirs.html" title="Sparse Directories">the section called “Sparse Directories”</a>) but any paths
        affected by the diff which are <span class="quote">“<span class="quote">missing</span>”</span> due to the
        sparse working copy will be skipped—this is probably
        <span class="emphasis"><em>not</em></span> what you intended!</p>
        </div>
        <div class="footnote">
          <p><sup>[<a id="ftn.idp12341040" href="#idp12341040" class="para">37</a>] </sup>Only
        Subversion 1.8 supports this reuse of a feature branch.  Earlier
        versions require some special handling before a feature branch
        can be reintegrated more than once.  See the earlier version of
        this chapter for more information: <a class="ulink" href="http://svnbook.red-bean.com/en/1.7/svn.branchmerge.basicmerging.html#svn.branchemerge.basicmerging.reintegrate" target="_top">http://svnbook.red-bean.com/en/1.7/svn.branchmerge.basicmerging.html#svn.branchemerge.basicmerging.reintegrate</a></p>
        </div>
        <div class="footnote">
          <p><sup>[<a id="ftn.idp12371936" href="#idp12371936" class="para">38</a>] </sup>By <span class="quote">“<span class="quote">direction</span>”</span>
      we mean either trunk-to-branch (automatic sync) or branch-to-trunk
      (automatic reintegrate) merges.</p>
        </div>
        <div class="footnote">
          <p><sup>[<a id="ftn.idp12419072" href="#idp12419072" class="para">39</a>] </sup>This is a good example of inoperative merge
        revisions.</p>
        </div>
        <div class="footnote">
          <p><sup>[<a id="ftn.idp12450464" href="#idp12450464" class="para">40</a>] </sup>The
        Subversion project has plans, however, to someday implement a
        command that would accomplish the task of permanently deleting
        information.  In the meantime, see
        <a class="xref" href="svn.reposadmin.maint.html#svn.reposadmin.maint.tk.svndumpfilter" title="svndumpfilter">the section called “svndumpfilter”</a> for a
        possible workaround.</p>
        </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.using.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.advanced.html">Next</a></td>
        </tr>
        <tr>
          <td width="40%" align="left" valign="top">Using Branches </td>
          <td width="20%" align="center">
            <a accesskey="h" href="index.html">Home</a>
          </td>
          <td width="40%" align="right" valign="top"> Advanced Merging</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>