* subversion/libsvn_repos/repos.c
[svn.git] / www / merge-tracking / func-spec.html
blob9f1b7978c5d5059a5b595fa4ebc4a19333b9de4e
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
5 <style type="text/css"> /* <![CDATA[ */
6 @import "../branding/css/tigris.css";
7 @import "../branding/css/inst.css";
8 /* ]]> */</style>
9 <link rel="stylesheet" type="text/css" media="print"
10 href="../branding/css/print.css"/>
11 <script type="text/javascript" src="../branding/scripts/tigris.js"></script>
12 <title>Merge Tracking Functional Specification</title>
13 </head>
15 <body>
16 <div class="h1">
17 <h1>Merge Tracking Functional Specification</h1>
19 <p><a href="index.html">Merge tracking</a> functional specification.
20 Describes Subversion 1.5.0, except where noted as
21 <i>unimplemented</i>. This is a living specification, which will
22 change as features are added or refined.</p>
24 <div class="h2" id="merge">
25 <h2>Merge operations</h2>
27 <p>Merge operations involving a single source URL (e.g. <code>svn
28 merge -cN URL</code>) allow the revision range and source URL
29 parameters to be optional. The revision range defaults to "all
30 unmerged revisions", while the source URL is inferred using a
31 combination of merge info and copy history. When a revision range is
32 not provided, merge operations are not able to "revert" changes
33 (e.g. a la <code>svn merge -c -7 URL</code>).</p>
35 <p>See the <a href="#repeated-merge">repeated merge</a> section below
36 for discussion of various merge algorithms, and details on the merge
37 algorithm used.</p>
39 <p>Merge info is <em>not taken into consideration for three-way
40 merges</em>, merge operations which do not specify identical "from"
41 and "to" URLs (e.g. <code>svn merge FROM_URL@REV1 TO_URL@REV2</code>).
42 In the future, Subversion will likely support this, but currently
43 lacks sufficient history and merge info between the repository and
44 client to perform this operation in a reasonable manner. The primary
45 use case this will impact is vendor branches.</p>
47 </div> <!-- merge -->
49 <div class="h2" id="diff-status">
50 <h2>Diff/Status operations</h2>
52 <p>Output is shown the same as pre-Merge Tracking, except for:</p>
54 <ul>
55 <li>Diffs pretty-print changes to merge info in an easily
56 human-readable form.</li>
58 <li>Diffs sometimes report spurious property changes from merge info
59 (bug?).</li>
61 <li>Status represents changes to the merge info for the root of a
62 tree as a property change.</li>
63 </ul>
65 </div> <!-- diff-status -->
68 <div class="h2" id="copy-move">
69 <h2>Copy/Move operations</h2>
71 <p>Copy and move operations handle two types of merge info:</p>
73 <dl>
74 <dt>Explicit</dt>
75 <dd>The pre-existing value of the <code>svn:mergeinfo</code>
76 property on the source path.</dd>
78 <dt>Implicit</dt>
79 <dd>All revisions represented by the object at the source path (from
80 its "appeared in" revision to its current revision).</dd>
81 </dl>
83 <div class="h3" id="ra-copy-move">
84 <h3>Repository Access operation</h3>
86 <p>Copy/move operations which contact the repository include:</p>
88 <ul>
89 <li>WC to URL</li>
90 <li>URL to WC</li>
91 <li>URL to URL</li>
92 </ul>
94 <p>These operations always propogate both explicit and implicit merge
95 info. Other than the inclusion of merge info, operation is
96 effectively the same as pre-Merge Tracking.</p>
98 </div> <!-- ra-copy-move -->
100 <div class="h3" id="wc-wc-copy-move">
101 <h3>Working Copy to Working Copy operation</h3>
103 <p>Pre-Merge Tracking, WC to WC operations occurred offline (e.g. with
104 no repository access). This is a typical behavior of refactoring
105 tools (e.g. IDEs like Eclipse), and is very useful when offline
106 (e.g. on an airplane or subway, or at a cafe).</p>
108 <p>However, to propogate merge info during copy/move operations,
109 access to both a path's comprehensive merge info and its history is
110 necessary. To preserve offline operation, the Merge Tracking
111 implementation supports two modes:</p>
113 <ul>
114 <li>A compatibility mode, which neither contacts the repository, nor
115 does any merge info propogation (unless a copy source's merge info
116 has been locally modified, in which its value is propogated the as
117 any Subversion revision property). This is the default mode of
118 operation.</li>
120 <li>A mode which requires repository access (e.g. isn't offline),
121 but which propogates all merge info from source path to
122 destination. This mode is activated via the
123 <code>--use-merge-history</code> option.</li>
124 </ul>
126 <p>This behavior is comparable to the difference between <code>svn
127 status</code> and <code>svn status -u</code>.</p>
129 <p>While some state indicating delayed merge info retrieval and
130 handling could instead be stored in WC to preserve offline operation,
131 there are complications with this when subsequent uncommited revert
132 operations should change the merge info (we'd have to store negative
133 merge info in the WC).</p>
135 </div> <!-- wc-wc-copy-move -->
137 </div> <!-- copy-move -->
139 <div class="h2" id="sparse-checkouts">
140 <h2>Sparse Checkouts</h2>
142 <p>When merging to a WC with sparsely populated directories, non-inheritable
143 mergeinfo for the merge is set on the deepest directories present.</p>
145 <ul>
146 <li>Directories with depth == empty: The directory gets non-inheritable
147 mergeinfo.</li>
149 <li>Directories with depth == files: The directory gets non-inheritable
150 mergeinfo. Any child files present get inheritable mergeinfo (not to imply
151 files ever have anything but inheritable mergeinfo, they shouldn't!).</li>
153 <li>Directories with depth == imediates: The directory and any child files
154 present get inheritable mergeinfo. And directory children present get
155 non-inheritable mergeinfo.</li>
157 </ul>
159 </div> <!-- sparse-checkouts -->
161 <div class="h2" id="switched-paths">
162 <h2>Switched Paths</h2>
164 <p>Switched paths are treated as the root of the working copy regarding
165 merge info inheritance and elision, specifically:</p>
167 <ul>
168 <li>Merge rev N to switched PATH which has no explicit merge info: PATH
169 does not inherit merge info from its working copy ancestors. PATH gets
170 merge info for rev N plus any inherited mergeinfo from the repository.</li>
172 <li>Merge rev N to PATH with switched CHILD: If CHILD has no explicit
173 mergeinfo it does not inherit merge info from its working copy ancestors.
174 Instead CHILD gets merge info for rev N plus any inherited mergeinfo from
175 the repository. Regardless of wether CHILD has explicit mergeinfo,
176 CHILD's immediate PARENT (which may be the same as PATH) gets
177 non-inheritable mergeinfo added for rev N. If PARENT didn't have
178 pre-existing mergeinfo it will have mergeinfo added. If CHILD has an
179 unswitched SIBLING, then SIBLING will get a full set of mergeinfo since
180 SIBLING and CHILD's common PARENT gets non-inheritable mergeinfo for this
181 merge. Again, like PARENT, if SIBLING does not have pre-existing
182 mergeinfo it will have mergeinfo added.
183 </li>
185 <li>Elision: Merge info on switched paths never elides.</li>
187 <li>Switch PATH which has <em>committed</em> merge info or switch PATH which
188 has a CHILD with <em>committed</em> mergeinfo: PATH's / CHILD's mergeinfo
189 is <em>replaced</em> by the explicit mergeinfo from the repository.</li>
191 <li>Switch PATH which has <em>local</em> merge info or switch PATH which has
192 a CHILD with <em>local</em> mergeinfo: PATH's / CHILDS's local mergeinfo
193 is <em>merged</em> with explicit or inherited mergeinfo from the repository.
194 </li>
195 </ul>
197 </div> <!-- switched-paths -->
199 <div class="h2" id="prop-change">
200 <h2>Property change operations</h2>
202 <p>Property changes from <code>propedit</code>, <code>propset</code>,
203 and <code>propdel</code> operations can be used to change merge info.
204 However, as these operations do not attempt to address merge info
205 inheritance, changes to merge info on a directory affects merge info
206 on any child paths.</p>
208 </div> <!-- prop-change -->
210 <div class="h2" id="mergeinfo-elision">
211 <h2>Merge Info Elision</h2>
213 <p>Merge info set on a working copy "child" path as a result of a merge,
214 switch, or update, may fully/partially elide to the path's nearest working
215 copy or repository ancestor with fully/partially equivalent merge info.
216 Elision is attempted as part of any merge/switch/update:</p>
218 <div class="h3" id="full-elision">
219 <h3>Full Elision</h3>
221 <ul>
222 <li><b>Simple Equivalency</b>: The merge info on a child path and the merge
223 info on its nearest ancestor both map the same set of source paths to the
224 same revision ranges. The "same" source path is taken to mean that the only
225 differences between the two are relative path differences which are exactly
226 the same as the relative path differences between the child and the ancestor,
227 e.g.:<pre>
228 Properties on '/A_COPY_2':
229 svn:mergeinfo : /A:4-9
230 /A_COPY:3
231 Properties on '/A_COPY_2/B/E':
232 svn:mergeinfo : /A/B/E:4-9
233 /A_COPY/B/E:3</pre>
234 The merge info on 'A_COPY_2/B/E' elides to 'A_COPY_2' because the only
235 differences between the merge source paths on each is 'B/E' which is the same
236 as the relative path difference between 'A_COPY_2/B/E' and 'A_COPY_2'.
237 </li>
238 </ul>
240 <ul><li><b>Semantic Equivalency</b>: Excepting paths <i>unique</i> to the child
241 or ancestor which map to empty revision ranges, the merge info between the
242 child and ancestor is otherwise equivalent per the definition of simple
243 equivalency, e.g.:<pre>
244 Properties on '/A_COPY_2':
245 svn:mergeinfo : /A:4-9
246 /A_COPY:
247 Properties on '/A_COPY_2/B/E':
248 svn:mergeinfo : /A/B/E:4-9
250 Properties on '/A_COPY_2':
251 svn:mergeinfo : /A:4-9
252 Properties on '/A_COPY_2/B/E':
253 svn:mergeinfo : /A/B/E:4-9
254 /A_COPY/B/E:</pre>
255 In both of the above examples the merge info on 'A_COPY_2/B/E' elides to
256 'A_COPY_2'.
257 </li>
258 </ul>
260 <ul><li><b>Empty Revision Range Equivalency</b>: If the merge info on a path is
261 made up entirely of paths mapped to empty revision ranges and the path has no
262 ancestor with merge info then the merge info fully elides.
263 </li>
264 </ul>
266 </div> <!-- full-elision -->
268 <div class="h3" id="partial-elision">
269 <h3>Partial Elision</h3>
271 <ul>
272 <li><b>Partial Equivalency</b>: Only the merge source paths <i>unique</i> to
273 the child which map to empty revision ranges will elide if the merge info
274 between the child and ancestor is otherwise non-equivalent, e.g.:<pre>
275 Properties on '/A_COPY_2':
276 svn:mergeinfo : /A:4-6
277 Properties on '/A_COPY_2/B/E':
278 svn:mergeinfo : /A/B/E:5
279 /A_COPY/B/E:</pre>
280 The empty revision range merge info from 'A_COPY/B/E' on 'A_COPY_2/B/E'
281 elides, leaving:<pre>
282 Properties on '/A_COPY_2':
283 svn:mergeinfo : /A:4-6
284 Properties on '/A_COPY_2/B/E':
285 svn:mergeinfo : /A/B/E:5</pre>
286 </li>
287 </ul>
289 </div> <!-- partial-elision -->
291 <div class="h3" id="non-inheritable-elision">
292 <h3>Elision and Non-Inheritable Revision Ranges</h3>
295 The above rules apply only to mergeinfo without non-inheritable revision
296 ranges. Mergeinfo with non-inheritable revision ranges cannot elide or be
297 elided to.
298 </p>
300 </div> <!-- non-inheritable-elision -->
302 </div> <!-- mergeinfo-elision -->
304 <div class="h2" id="merge-history">
305 <h2>Merge History</h2>
307 <p>Merge Tracking meta data is stored in housekeeping properties
308 (e.g. <code>svn:mergeinfo</code>).</p>
310 <div class="h3" id="merge-history-mainpulation">
311 <h3>Merge History Manipulation</h3>
313 <p>While direct manipulation of housekeeping properties can be used to
314 change merge info, commands to manipulate this information have been
315 provided. Either style of operation supports adjustment of merge info
316 when <a href="requirements.html#manual-merge">manual merges</a> occur,
317 and can also be used to fulfill <a
318 href="requirements.html#revision-blocking">block changes undesired for
319 merge</a> (later, this might be better-addressed by a separate
320 housekeeping property).</p>
322 <ul>
323 <li><code>merge --record-only</code> adds (or subtracts, if a
324 reversed revision range is supplied) merge info for a path
325 <i>without performing the actual merge</i>.</li>
327 <li><code>propedit</code>/<code>propset</code> changes merge info
328 for a path.</li>
330 <li><code>propdel</code> removes merge info for a path.</li>
331 </ul>
333 </div> <!-- meta-data-mainpulation -->
335 <div class="h3" id="merge-history-audit">
336 <h3>Merge History Audit and Query</h3>
338 <p>The <a href="#commutative-author-and-rev">Commutative Author and Revision
339 Reporting</a> feature has been implemented, and will be included in 1.5.0.</p>
341 <p>These features may or may not be completed for 1.5.0.</p>
343 <ul>
344 <li><a href="#show-changesets-available">Changeset Merge
345 Availability</a> (<i>unimplemented</i>)</li>
347 <li><a href="#find-changeset">Find Changeset</a>
348 (<i>unimplemented</i>)</li>
349 </ul>
351 <div class="h4" id="show-changesets-available">
352 <h4>Changeset Merge Availability</h4>
354 <p>Show changesets available for merge/already merged from one or more
355 merge source(s). The command-line client's default output format
356 should be equivalent to that of <code>svn log</code>, and allow for
357 XML-formatted output (for machine parsing). Blue sky, the
358 command-line could also produce an output format equivalent to that of
359 <code>svn diff</code>.</p>
361 <p>Recent discussion can be found <a
362 href="http://subversion.tigris.org/servlets/ReadMsg?listName=dev&amp;msgNo=128233"
363 >here</a>. Development is tracked <a
364 href="http://subversion.tigris.org/issues/show_bug.cgi?id=2820">here</a>.</p>
366 <p>The <a href="requirements.html#change-set-availability">Show
367 Changesets Blocked from Merging</a> portion of this feature is
368 scheduled for implementation post-1.5, and is dependent upon the <a
369 href="requirements.html#revision-blocking">revision blocking</a>
370 feature slated for the same timeframe.</p>
372 </div> <!-- show-changesets-available -->
374 <div class="h4" id="find-changeset">
375 <h4>Find Changeset</h4>
377 <p>Show where a changeset has been merged from/merged to, providing
378 merging revision, URL, and rangelist. The command-line client should
379 allow for XML-formatted output (for machine parsing).</p>
381 <p>Recent discussion can be found <a
382 href="http://subversion.tigris.org/servlets/ReadMsg?listName=dev&amp;msgNo=128233"
383 >here</a>. Development is tracked <a
384 href="http://subversion.tigris.org/issues/show_bug.cgi?id=2835">here</a>.</p>
386 <p>The <a href="requirements.html#find-changeset">Find Paths
387 containing Specific Incarnation of Versioned Resource</a> portion of
388 this feature is not yet scheduled for implementation.</p>
390 </div> <!-- find-changeset -->
392 <div class="h4" id="commutative-author-and-rev">
393 <h4>Commutative Author and Revision Reporting</h4>
395 <div class="h5" id="auditing-scope">
396 <h5>Scope</h5>
398 <p>The following commands which show username and merge information should
399 respect merge information and support <a
400 href="requirements.html#commutative-author-and-rev">Commutative
401 Reporting</a>. These commands are:</p>
403 <ul>
404 <li><code>svn log</code></li>
405 <li><code>svn blame</code></li>
406 </ul>
408 <p><code>svn info</code>, <code>svn ls --verbose</code> and <code>svn
409 status --show-updates</code> are purposely not included in this list.
410 While one would typically need more information than they can
411 reasonably provide alone, adding more output to these commands would
412 clutter their command-line interface, reducing their utility. Merge
413 Tracking-aware API support for the underlying functionality provided
414 by these commands may be added at some point in the future (e.g. for
415 use by third-party clients like <a href="http://tortoisesvn.tigris.org/"
416 >TortoiseSVN</a>).</p>
418 <p>A new switch, <code>--use-merge-history</code>, along with a
419 corresponding single-character shortcut (<code>-g</code>), will be
420 introduced for the toggle merge information. Using it will enable these
421 commands to show the additional information gleaned from parsing and
422 processing the merge info on the targets in question. This switch will
423 also work with <code>--xml</code> to include additional merge
424 information. The new functionality added by
425 <code>--use-merge-history</code> is as follows.</p>
427 <dl>
428 <dt><code>svn log</code></dt>
429 <dd><p>The original log message(s), in the current format, with the
430 addition of a list of revisions and merge source paths that have
431 been merged into the target. The output for <code>log</code> should
432 be consistent with the <code>diff</code> output for the
433 <code>svn:mergeinfo</code> property.</p>
435 <p>The <code>--verbose</code> switch will output the log information
436 for the merged revisions in place of the information for the revision
437 in which the merge occured. Each of the original message(s) will have an
438 additional line indicating that it is the result of a merge, and which
439 revision the merge occured in.</p>
441 <p>For instance, if Alice was the original author of r12, Bob was the
442 orginial author of r14, and Chuck merged them both r12 and r14 as part
443 of r24, the output of <code>svn log --use-merge-history</code>
444 will look like this:</p>
445 <pre>
446 ------------------------------------------------------------------------
447 r24 | chuck | 2007-04-30 10:18:01 -0500 (Mon, 16 Apr 2007) | 1 line
449 Merge r12 and r14 from branch to trunk.
450 ------------------------------------------------------------------------
451 r14 | bob | 2007-04-16 18:50:29 -0500 (Mon, 16 Apr 2007) | 1 line
452 Result of a merge from: r24
454 Remove inadvertent changes to Death-Ray-o-Matic introduced in r12.
455 ------------------------------------------------------------------------
456 r12 | alice | 2007-04-16 19:02:48 -0500 (Mon, 16 Apr 2007) | 1 line
457 Result of a merge from: r24
459 Fix frapnalyzer bug in frobnicator.
460 </pre>
462 <p>Using the same example, the output of <code>svn log
463 --use-merge-history --verbose</code> will look like:</p>
465 <pre>
466 ------------------------------------------------------------------------
467 r24 | chuck | 2007-04-30 10:18:01 -0500 (Mon, 16 Apr 2007) | 1 line
468 Changed paths:
469 M /trunk/death-ray.c
470 M /trunk/frobnicator/frapnalyzer.c
472 Merge r12 and r14 from branch to trunk.
473 ------------------------------------------------------------------------
474 r14 | bob | 2007-04-16 18:50:29 -0500 (Mon, 16 Apr 2007) | 1 line
475 Changed paths:
476 M /branches/world-domination/death-ray.c
477 Result of a merge from: r24
479 Remove inadvertent changes to Death-Ray-o-Matic introduced in r12.
480 ------------------------------------------------------------------------
481 r12 | alice | 2007-04-16 19:02:48 -0500 (Mon, 16 Apr 2007) | 1 line
482 Changed paths:
483 M /branches/world-domination/frobnicator/frapnalyzer.c
484 M /branches/world-domination/death-ray.c
485 Result of a merge from: r24
487 Fix frapnalyzer bug in frobnicator.
488 </pre>
490 <p>If r12 was itself a merge of r9 and r10, <code>svn log
491 --use-merge-history</code> for r24 will look like this:</p>
493 <pre>
494 ------------------------------------------------------------------------
495 r24 | chuck | 2007-04-30 10:18:01 -0500 (Mon, 16 Apr 2007) | 1 line
497 Merge r12 and r14 from branch to trunk.
498 ------------------------------------------------------------------------
499 r14 | bob | 2007-04-16 18:50:29 -0500 (Mon, 16 Apr 2007) | 1 line
500 Result of a merge from: r24
502 Remove inadvertent changes to Death-Ray-o-Matic introduced in r12.
503 ------------------------------------------------------------------------
504 r12 | alice | 2007-04-16 19:02:48 -0500 (Mon, 16 Apr 2007) | 1 line
505 Result of a merge from: r24
507 Fix frapnalyzer bug in frobnicator.
508 ------------------------------------------------------------------------
509 r10 | alice | 2007-04-16 19:02:28 -0500 (Mon, 16 Apr 2007) | 1 line
510 Result of a merge from: r12, r24
512 Fix frapnalyzer documentation.
513 ------------------------------------------------------------------------
514 r9 | bob | 2007-04-16 19:01:48 -0500 (Mon, 16 Apr 2007) | 1 line
515 Result of a merge from: r12, r24
517 Whitespace fixes. No functional change.
518 </pre>
520 <p>In each case, merged revisions will be grouped together under the merging
521 revisions, and sorted by revision number. This may mean that not all log
522 messages will be in revision number order, but changes will be presented in
523 the order they were actually made.</p>
525 <p>Output for <code>svn log -g --xml</code> will exploit the tree structure
526 of XML to include child messages as subelements of the corresponding parent
527 log messages. Consumers can use the location of a particular log message in
528 the tree to determine its ancestry.</p>
530 <p>This output may be useful for auditing purposes to those migrating from
531 <a href="http://www.orcaware.com/svn/wiki/Svnmerge.py">svnmerge.py</a>, as
532 a replacement for repeating the entirety of the merged ranges' log
533 messages in the log message for the commit of a merge (e.g. svnmerge.py's
534 generated <em>svnmerge-commit-message.txt</em> file).</p>
536 </dd>
538 <dt><code>svn blame</code></dt>
539 <dd>
540 <p>Reuse the existing author and revision columns. Instead of listing
541 the merging author and revision, list the original author and revision of
542 that line. Unlike other commands, we do not need to worry about multiple
543 source revisions, because each line can have at most one author.</p>
545 <p>The output of <code>svn blame</code> may be the following:</p>
546 <pre>
547 2 alice This is the file 'iota'.
548 14 bob 'A' has changed a bit, with 'upsilon', and 'xi'.
549 </pre>
551 <p>Using the <code>-g</code> switch will show the author who most recently
552 changed the line, independent of which branch it was changed on (so long as
553 the changes have been merged). If Chuck made changes to the file in r11,
554 which was then merged in r14, the output of <code>svn blame -g</code> for the
555 same file may look like this:</p>
556 <pre>
557 2 alice This is the file 'iota'.
558 11 chuck 'A' has changed a bit, with 'upsilon', and 'xi'.
559 </pre>
561 <p>The <code>--verbose</code> flag also triggers additional information.
562 In addition to the date of the revision, <code>--verbose</code>, in
563 combination with <code>-g</code>, also displays the the original path, relative
564 to the repository root, where the modifications were made. Given the above
565 example, <code>svn blame -g --verbose</code> will be something like this:</p>
566 <pre>
567 2 alice 2007-06-07 10:16:49 -0500 (Thu, 07 Jun 2007) /trunk/iota This is the file 'iota'.
568 11 chuck 2007-06-07 12:29:48 -0500 (Thu, 07 Jun 2007) /branches/a/iota 'A' has changed a bit, with 'upsilon', and 'xi'.
569 </pre>
571 <p>The output of <code>svn blame -g --xml</code> is not limited by size, and
572 will include all available information.</p>
574 </dd>
575 </dl>
577 <p>For commits which remove merge info (e.g. reverts),
578 <code>--use-merge-history</code> will trace back to the original author. For
579 example if Alice makes a commit to code previously modified by Bob (committed
580 with no merge history), and Alice's commit is subsequently reverted by Chris,
581 we should show Bob as the author. If Bob's commit was itself the result of a
582 merge, we should recurse until we find a commit which did not add merge info
583 (the leaf node), and assume its author.</p>
585 </div> <!-- auditing-scope -->
587 <div class="h5" id="auditing-questions">
588 <h5>Pending Questions</h5>
590 </div> <!-- auditing-questions -->
592 <div class="h5" id="auditing-extra-credit">
593 <h5>Additional Features</h5>
595 <p>Although not part of the initial implementation, additional features have
596 been suggested:</p>
598 <ul>
599 <li>A configuration option to always enable
600 <code>--use-merge-history</code>.
601 </li>
602 </ul>
604 </div> <!-- auditing-extra-credit -->
606 </div> <!-- commutative-author-and-rev -->
608 </div> <!-- meta-data-audit -->
610 </div> <!-- meta-data -->
612 <div class="h2" id="repeated-merge">
613 <h2>Repeated Merge</h2>
615 <p>There are two general schemes for solving the <a
616 href="requirements.html#repeated-merge">repeated merge</a> problem.
617 Subversion 1.5 uses the <a href="#mrca-merge">Most Recent Common
618 Ancestor (MRCA)</a> approach. If a later version of Subversion
619 (e.g. 2.0) overhauls the Merge Tracking implementation, it'll likely
620 use the <a href="#as-merge">Ancestry Set (AS)</a> approach.</p>
622 <p>Either solution also supports the <a
623 href="requirements.html#cherry-picking">cherry picking</a>, <a
624 href="requirements.html#rollback-merge">rollback</a>, and <a
625 href="requirements.html#properties">property merging</a> use cases. A
626 <a href="requirements.html#merge-previews">merge preview</a> which is
627 lighter-weight than an uncommitted merge into a WC is not
628 supported.</p>
630 <div class="h3" id="mrca-merge">
631 <h3>The Most Recent Common Ancestor approach</h3>
633 <p>In this scheme, An optional set of merge sources in each
634 node-revision. When asked to do a merge with only one source (that
635 is, just <code>svn merge URL</code>, with no second argument), you
636 compute the most recent ancestor and do a three-way merge between the
637 common ancestor, the given URL, and the WC.</p>
639 <p>To compute the most recent ancestor, you chain off the immediate
640 predecessors of each node-revision. The immediate predecessors are
641 the direct predecessor (the most recent node-revision within the node)
642 and the merge sources. An interleaved breadth-first search should
643 find the most recent common ancestor.</p>
645 </div> <!-- mrca-merge -->
647 <div class="h3" id="as-merge">
648 <h3>The Ancestry Set approach</h3>
650 <p>In this scheme, you record the full ancestry set for each
651 node-revision -- that is, the set of all changes which are accounted
652 for in that node-revision. (How you store this ancestry set is
653 unimportant; the point is, you need a reasonably efficient way of
654 determining it when asked.) If you are asked to "svn merge URL", you
655 apply the changes present in URL's ancestry but absent in WC's
656 ancestry. Note that this is not a single three-way merge; you may
657 have to apply a large number of disjoint changes to the WC.</p>
659 <p>For a longer description of this approach, see the <a
660 href="/design.html#model.merging-and-ancestry">"Merging and Ancestry"
661 section</a> of the original <a href="/design.html">design doc</a>.</p>
663 <div class="h4" id="aslb-merge">
664 <h4>Ancestry-Sensitive Line-Based Merge</h4>
666 <p>Make 'hunks' of contextually-merged text sensitive to ancestry.</p>
668 <p>A high-resolution version of <a
669 href="requirements.html#repeated-merge">repeated merge</a>. Rather
670 than tracking whole changesets, we track the lineage of specific lines
671 of code within a file. The basic idea is that when re-merging a
672 particular hunk of code, the contextual-merging process is aware that
673 certain lines of code already represent the merging of particular
674 lines of development. Jack Repenning has a great example of this from
675 ClearCase (see ASCII diagram below).</p>
677 <p>See the <a href="../variance-adjusted-patching.html">variance
678 adjusted patching</a> document for an extended discussion of how to
679 implement this by composing diffs; see <a
680 href="http://svn.collab.net/svn-doxygen/svn__diff_8h.html#a11"
681 ><code>svn_diff_diff4()</code></a> for an implementation of same. We
682 may be closer to ancestry-sensitive merging than we think.</p>
684 <p>Here's an example demonstrating how individual lines of code can be
685 tracked. In this diagram, we're drawing the lineage of a single file,
686 with time flowing downwards. The file begins life with three lines of
687 text, "1\n2\n\3\n". The file then splits into two lines of
688 development.</p>
690 <pre>
694 / \
695 / \
696 / \
697 one 1
698 two 2.5
699 three 3
700 | \ |
701 | \ |
702 | \ |
703 | \ |
704 | \ one ## This node is a human's
705 | two-point-five ## merge of two sides.
706 | three
710 one one
711 Two two-point-five
712 three newline
713 \ three
714 \ |
722 one ## This node is a human's
723 Two-point-five ## merge of the changes
724 newline ## since the last merge.
725 three
726 </pre>
728 <p>It's the second merge that's important here.</p>
730 <p>In a system like Subversion, the second merge of the left branch to
731 the right will fail miserably: the whole file's contents will be
732 placed within conflict markers. That's because it's trying to dumbly
733 apply a patch that changes "1\n2\n3" to "one\nTwo\nthree", and the
734 target file has no matching lines at all.</p>
736 <p>A smarter system (like Clearcase) would remember that the previous
737 merge had happened, and specifically notice that the lines "one" and
738 "three" are the results of that previous merge. Therefore, it would
739 ask the human only to deal with the "Two" versus "two-point-five"
740 conflict; the earlier changes ("1\n2\n3" to "one\ntwo\nthree") would
741 already be accounted for.</p>
743 </div> <!-- aslb-merge -->
745 </div> <!-- as-merge -->
747 <div class="h3">
748 <h3>Comparisons, Arguments, and Questions</h3>
750 <p>AS allows you to merge changes from a branch out of order, without
751 doing any bookkeeping. MRCA requires you to merge changes from a
752 branch in order.</p>
754 <p>MRCA is simpler to implement, since it results in a three-way merge
755 (which is well-understood by Subversion). However, it may not handle
756 all edge cases. For instance, it may break down faster if the merging
757 topology is not hierarchical.</p>
759 <p>MRCA may be easier for users to understand, even though AS is
760 probably simpler to a mathematician.</p>
762 <p>Consistency with other modern version controls systems is
763 desirable.</p>
765 <p>If a user asks to merge a directory, should we apply MRCA or AS to
766 each subdirectory and file to determine what ancestor(s) to use? Or
767 should we apply MRCA or AS just once, to the directory itself? The
768 latter approach seems simpler and more efficient, but will break down
769 quickly if the user wants to merge subdirectories of a branch in
770 advance of merging in the whole thing.</p>
772 </div> <!-- h3 -->
774 </div> <!-- repeated-merge -->
777 <div class="h2" id="conflict-resolution">
778 <h2>Merge Conflict Resolution</h2>
780 <p>Merging inevitably produces conflicts which cannot be resolved by
781 an algorithm alone. In such a case, human intervention is required to
782 resolve the conflicts. The merge algorithm used by Subversion's Merge
783 Tracking implementation makes this problem worse, since it breaks a
784 requested merge range into several merges to avoid <a
785 href="requirements.html#repeated-merge">repeating merges</a> which
786 have already been applied to a merge target or its children. After a
787 conflict is encountered, merges of subsequent revision ranges must be
788 aborted, since <a
789 href="http://svn.collab.net/repos/svn/trunk/notes/tree-conflicts.txt"
790 >tree conflicts</a> or previous content conflicts cannot be reliably
791 merged into (e.g. you can't merge into a file that either isn't there
792 or which you could potentially merge inside one side of a conflict
793 marker).</p>
795 <p>To help alleviate the pain of conflict resolution, a merge <a
796 href="design.html#conflict-resolution">conflict resolution
797 callback</a> can be employed by Subversion clients. This callback is
798 invoked whenever merge conflicts are encountered, and can takes steps
799 like launching a graphical merge tool (for interactive conflict
800 resolution), or following a pre-specified directive like "always use
801 the version from my merge source". This last implementation can be
802 used to support the <a href="requirements.html#automated-merge">SCM
803 automated merge</a> use case.</p>
805 <p>The command-line client includes a merge conflict resolution
806 callback which behaves much like <em>svk</em>, when in interactive
807 mode prompting for how to resolve each conflicted file or property
808 value. When in non-interactive mode (or configured to disallow
809 interactive conflict resolution via <code>[miscellany]
810 interactive-conflicts = no</code>), conflict resolution is postponed
811 until post-merge (as in pre-1.5 releases). See the <a
812 href="../svn_1.5_releasenotes.html">1.5 release notes</a> for an
813 example.</p>
815 <p>In a post-1.5 release, the command-line client will provide an
816 interactive conflict resolution option to display some context for
817 each conflict in a path or property value, and prompt for how to
818 resolve it. The merge algorithm will attempt to continue applying
819 more of the requested merge after conflict is encountered, merging
820 what it can around the conflicted area of the WC, and possibly
821 supporting an option to complete the remainder of an unfinished merge
822 operation after conflicts have been resolved manually.</p>
824 <p>Related discussion from the dev@ mailing list can be found
825 here:</p>
827 <ul>
828 <li><a
829 href="http://subversion.tigris.org/servlets/ReadMsg?listName=dev&amp;msgNo=128091"
830 >First draft of interactive conflict resolution callback API and
831 command-line client implementation</a></li>
833 <li><a
834 href="http://subversion.tigris.org/servlets/ReadMsg?listName=dev&amp;msgNo=121756"
835 >Feedback solicited from IDE developers</a></li>
837 <li><a
838 href="http://subversion.tigris.org/servlets/ReadMsg?listName=dev&amp;msgNo=121263"
839 >Original API proposal</a></li>
840 </ul>
842 <p><a href="http://subversion.tigris.org/issues/show_bug.cgi?id=2022"
843 >Issue #2022</a> is loosely related.</p>
845 <div class="h3" id="distributable-resolution">
846 <h3>Distribution of Conflict Resolution</h3>
848 <p>No explicit facility is provided for distribution of conflict
849 resolution. To support this use case, developers can co-ordinate with
850 each other to resolve merge conflicts on portions of a tree, and trade
851 patches.</p>
853 </div> <!-- distributable-resolution -->
855 </div> <!-- conflict-resolution -->
858 <div class="h2" id="migration-and-interoperability">
859 <h2>Migration and Interoperability</h2>
861 <div class="h3" id="migration">
862 <h3>Migration</h3>
864 <p>No explicit steps are necessary to migrate the content of a
865 pre-Merge Tracking repository. Only an upgrade to Subversion 1.5.0 is
866 necessary.</p>
868 <p>TODO: Merge meta data from svnmerge.py. Dan Berlin has written
869 Python code to perform this migration; it needs to be made available
870 in the <code>tools/server-side/</code> area of the distribution .</p>
872 </div> <!-- migration -->
874 <div class="h3" id="interoperability">
875 <h3>Interoperability</h3>
877 <p>Executive summary for client/repository inter-op:</p>
879 <ul>
880 <li>Older Subversion clients may <a href="requirements.html#compatibility"
881 >interact with a 1.5.x+ Subversion repository</a>, but will continue
882 to lack Merge Tracking functionality for:
884 <ul>
885 <li>Recording meta data about any merges performed.</li>
886 <li>Using merge meta data to avoid <a
887 href="requirements.html#repeated-merge">repeated merging</a>.</li>
888 </ul>
889 </li>
891 <li>1.5.x+ Subversion clients may interact with a older Subversion
892 repositories, with Merge Tracking functionality effectively
893 neutralized.</li>
894 </ul>
896 <p>Gory detail for client/repository inter-op:</p>
898 <ul>
899 <li>A repository 1.4.x- doesn't provide any way to retrieve
900 inherited merge info for a path (regardless of client version). For
901 a 1.5.x+ client which could theoretically make use of any merge info
902 available to it, this will typically neutralize its Merge Tracking
903 functionality. The one case where merge info might come into play
904 is when the merge info for a path is available locally (e.g. in the
905 client's WC); in this case, repeated merges may be avoided.</li>
907 <li>A 1.5.x client will record merge tracking meta data for merges
908 performed, regardless of repository version. However, a repository
909 1.4.x- won't know to do anything special with this merge info. When
910 the repository is upgraded to 1.5.x+, we'll retain this merge info
911 in the svn:mergeinfo property, but I'm not yet clear on what'll
912 happen to the sqlite merge info index. We may need some sort of
913 upgrade path here, but don't have one yet, and aren't promising
914 one.</li>
915 </ul>
917 <p>Subversion <a href="requirements.html#dump-load">dump files
918 continue to be fully portable</a> between pre- and post-Merge Tracking
919 versions of Subversion.</p>
921 </div> <!-- interoperability -->
923 </div> <!-- migration-and-interoperability -->
926 <div class="h2" id="related-documents">
927 <h2>Related Documents and Discussion</h2>
929 <ul>
930 <li><a href="http://subversion.tigris.org/merge-tracking/summit.html"
931 >CollabNet customer Merge Tracking Summit</a></li>
933 <li><a href="http://www.codeville.org/">Codeville</a> is reputed to
934 excel both in its usefulness of storage of line-history in the
935 <em>weave</em> format, and a corresponding merge algorithm:
937 <ul>
938 <li><a href="http://revctrl.org/PreciseCodevilleMerge">"Precise
939 Codeville merge"</a> algorithm and Python implementation. The
940 algorithm takes into account line history, history points where
941 they came from, the ability to retrieve ancestors' text as needed,
942 and a snapshot of the current file. It purports accuracy where
943 <a href="http://revctrl.org/CodevilleMerge">other algorithms fall
944 down</a>.</li>
946 <li>Bram Cohen describes <a
947 href="http://thread.gmane.org/gmane.comp.version-control.revctrl/2"
948 >the merge algorithm</a> (May 2005)</li>
949 </ul>
950 </li>
952 <li><a
953 href="http://svn.collab.net/repos/svn/trunk/subversion/libsvn_fs_base/notes/structure">Structure
954 of the Subversion FS BerkeleyDB backend</a></li>
956 </ul>
958 </div> <!-- related-documents -->
960 <p>$Date$</p>
962 </div> <!-- h1 -->
963 </body>
964 </html>