diff options
Diffstat (limited to '.html/dev/merging-structural-changes.html')
| -rw-r--r-- | .html/dev/merging-structural-changes.html | 156 |
1 files changed, 0 insertions, 156 deletions
diff --git a/.html/dev/merging-structural-changes.html b/.html/dev/merging-structural-changes.html deleted file mode 100644 index a019d9c..0000000 --- a/.html/dev/merging-structural-changes.html +++ /dev/null @@ -1,156 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <title> - The Codex » - Merging Structural Changes - </title> - - <link - rel='stylesheet' - type='text/css' - href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> - <link - rel="stylesheet" - type="text/css" - href="../media/css/reset.css"> - <link - rel="stylesheet" - type="text/css" - href="../media/css/grimoire.css"> -</head> -<body> - -<div id="shell"> - - <ol id="breadcrumbs"> - - <li class="crumb-0 not-last"> - - <a href="../">index</a> - - </li> - - <li class="crumb-1 not-last"> - - <a href="./">dev</a> - - </li> - - <li class="crumb-2 last"> - - merging-structural-changes - - </li> - - </ol> - - - - <div id="article"> - <h1 id="merging-structural-changes">Merging Structural Changes</h1> -<p>In 2008, a project I was working on set out to reinvent their build process, -migrating from a mass of poorly-written Ant scripts to Maven and reorganizing -their source tree in the process. The development process was based on having -a branch per client, so there was a lot of ongoing development on the original -layout for clients that hadn't been migrated yet. We discovered that our -version control tool, <a href="http://subversion.tigris.org/">Subversion</a>, was unable -to merge the changes between client branches on the old structure and the -trunk on the new structure automatically.</p> -<p>Curiousity piqued, I cooked up a script that reproduces the problem and -performs the merge from various directions to examine the results. Subversion, -sadly, performed dismally: none of the merge scenarios tested retained content -changes when merging structural changes to the same files.</p> -<h2 id="the-preferred-outcome">The Preferred Outcome</h2> -<p><img alt="Both changes survive the -merge." src="/media/dev/merging-structural-changes/ideal-merge-results.png"></p> -<p>The diagram above shows a very simple source tree with one directory, <code>dir-a</code>, -containing one file with two lines in it. On one branch, the file is modified -to have a third line; on another branch, the directory is renamed to <code>dir-b</code>. -Then, both branches are merged, and the resulting tree contains both sets of -changes: the file has three lines, and the directory has a new name.</p> -<p>This is the preferred outcome, as no changes are lost or require manual -merging.</p> -<h2 id="subversion">Subversion</h2> -<p><img alt="Subversion loses the content -change." src="/media/dev/merging-structural-changes/subversion-merge-results.png"></p> -<p>There are two merge scenarios in this diagram, with almost the same outcome. -On the left, a working copy of the branch where the file's content changed is -checked out, then the changes from the branch where the structure changed are -merged in. On the right, a working copy of the branch where the structure -changed is checked out, then the changes from the branch where the content -changed are merged in. In both cases, the result of the merge has the new -directory name, and the original file contents. In one case, the merge -triggers a rather opaque warning about a “missing file”; in the other, the -merge silently ignores the content changes.</p> -<p>This is a consequence of the way Subversion implements renames and copies. -When Subversion assembles a changeset for committing to the repository, it -comes up with a list of primitive operations that reproduce the change. There -is no primitive that says “this object was moved,” only primitives which say -“this object was deleted” or “this object was added, as a copy of that -object.” When you move a file in Subversion, those two operations are -scheduled. Later, when Subversion goes to merge content changes to the -original file, all it sees is that the file has been deleted; it's completely -unaware that there is a new name for the same file.</p> -<p>This would be fairly easy to remedy by adding a “this object was moved to that -object” primitive to the changeset language, and <a href="http://subversion.tigris.org/issues/show_bug.cgi?id=898">a bug report for just such a -feature</a> was filed in -2002. However, by that time Subversion's repository and changeset formats had -essentially frozen, as Subversion was approaching a 1.0 release and more -important bugs <em>without</em> workarounds were a priority.</p> -<p>There is some work going on in Subversion 1.6 to handle tree conflicts (the -kind of conflicts that come from this kind of structural change) more -sensibly, which will cause the two merges above to generate a Conflict result, -which is not as good as automatically merging it but far better than silently -ignoring changes.</p> -<h2 id="mercurial">Mercurial</h2> -<p><img alt="Mercurial preserves the content -change." src="/media/dev/merging-structural-changes/mercurial-merge-results.png"></p> -<p>Interestingly, there are tools which get this merge scenario right: the -diagram above shows how <a href="http://www.selenic.com/mercurial/">Mercurial</a> handles -the same two tests. Since its changeset language does include an “object -moved” primitive, it's able to take a content change for <code>dir-a/file</code> and -apply it to <code>dir-b/file</code> if appropriate.</p> -<h2 id="git">Git</h2> -<p>Git also gets this scenario right, <em>usually</em>. Unlike Mercurial, Git does not -track file copies or renames in its commits at all, prefering to infer them by -content comparison every time it performs a move-aware operation, such as a -merge.</p> - </div> - - - -<div id="comments"> -<div id="disqus_thread"></div> -<script type="text/javascript"> - /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ - var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname - - /* * * DON'T EDIT BELOW THIS LINE * * */ - (function() { - var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; - dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; - (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); - })(); -</script> -<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> -<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> -</div> - - - - <div id="footer"> - <p> - - The Codex — - - Powered by <a href="http://markdoc.org/">Markdoc</a>. - -<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/dev/merging-structural-changes.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/dev/merging-structural-changes.md">history</a>). - - </p> - </div> - -</div> -</body> -</html>
\ No newline at end of file |
