[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

tree conflicts (was: Re: merge performance (was: Re: Distributed Subversion))

From: Stefan Sperling <stsp_at_elego.de>
Date: Tue, 16 Jun 2009 13:10:11 +0100

On Mon, Jun 15, 2009 at 12:54:47PM -0600, Nathan Nobbe wrote:
> well, it looks like git is cognizant of tree conflicts (at least in some
> cases). i tested deleting a file in branchA and making a text change in
> branchB, here are the results in git when trying to merge
> CONFLICT (delete/modify): testFile.txt deleted in HEAD and modified in
> commit a text change. Version commit a text change of testFile.txt left in
> tree.

Yeah, that case works just fine in git.

> in the case above (completely replace subdir) im perhaps not running the
> test correctly... so i start out w/ a directory structure in trunk as such
> /testDir/innerTestDir/testFile.txt
> then i create a branch, branchA
> in branchA, i refactor the subdirectory testDir, and commit such that at
> that point the structure is as follows,
> /testDir/newInnerTestDir/newFile.txt
> and then similarly in trunk(master in git..), such that its structure is
> /testDir/randomInnerDir/randomNew.txt
> so w/o having to first merge trunk to branchA, i checkout trunk and run a
> merge from branchA. the result is the removal of testDir/innerTestDir, and
> now both newInnerTestDir and randomInnerDir are there in testDir. this
> seems reasonable to me, and additionally, ive been spared a merge (trunk ->
> branchA) that id have had to run in svn. i am however sort of seeing how
> you might want to be notified of this situation and act accordingly .. but
> im not sure if ive structured this test correctly; is this something that
> would tree conflict in svn?

I've written a lot of such test cases for my BSc thesis:

Your test is similar to what I called "git-directories-move1-moved",
the script to which reads:

  # $Id: git-directories-move1-moved.sh 179 2008-08-14 14:06:22Z stsp $
  . ./git-init.sh
  # Move a directory in repos
  (cd $repos && git mv gamma gamma.moved1)
  (cd $repos && git commit -a -m "renamed gammad")
  # Rename the same directory to a different name in repos2
  (cd $repos2 && git mv gamma gamma.moved2)
  # We need to commit here, else git won't detect a conflict.
  (cd $repos2 && git commit -a -m "renamed gamma, too")
  # Pull the rename into repos2 and merge
  (cd $repos2 && git pull)

All scripts are in http://stsp.name/thesis-tree-conflicts.tar.gz
and you need the git-init.sh from that tarball to run the above.
The scripts are fun to play with :)

Git detects the above situation, albeit it will flag the conflict
on files inside the renamed directory, not on the directory itself.
Subversion 1.6 flags this conflict on the renamed directory.

Note that my script above just renames the directory.
In your test, you've also renamed (or deleted) the file testFile.txt
inside the directory. So you modified the directory on top of renaming
the directory. That's even harder to detect, and in this case it defeats
git's ability to detect the conflict because git only looks at files.

That's why you ended up with both directories present next to each
other in the merge result. If that's what you wanted the result to be, fine.
If it's not what you wanted, have fun sorting out the mess for large
merges which refactor a lot of directories. If you even notice the
conflict -- in some environments, the person doing the merge is not
the person having done the refactoring, so errors can creep in more easily.
"I thought this directory was supposed to be here, isn't it?"
Add to this the possible tendency of users of distributed version
control systems to work in isolation, and they'd better track each others'
repositories very closely when moving many things around.

Subversion 1.6 does detect your situation, however, and correctly
flags it on the directory. The script below results in:

  $ svn merge file:////tmp/thesis-tree-conflicts/scripts/svn/svn-directories-move1-moved/repos/trunk svn-directories-move1-moved/branch
  --- Merging r2 through r5 into 'svn-directories-move1-moved/branch':
  A svn-directories-move1-moved/branch/gamma.moved1
  A svn-directories-move1-moved/branch/gamma.moved1/delta.moved
     C svn-directories-move1-moved/branch/gamma
  Summary of conflicts:
    Tree conflicts: 1
  $ svn status svn-directories-move1-moved/branch/gamma
  ! C svn-directories-move1-moved/branch/gamma
> local delete, incoming delete upon merge

Ideally, this would say "local move, incoming move upon merge",
instead of talking about deletes, but we're not quite there yet...

Anyway, if you know how to interpret what svn is trying to say,
you will realise that gamma has probably been refactored in an
incompatible way on the branch. If you're the merge-monkey and
you're not sure about this, you'd better ask someone from the
team which created the branch to help you resolve the conflict.

But also recall that due to issues discussed in the parent thread,
Subversion might take much longer to run your merge than git, which
might annoy the merge-monkey.
So again, it's all about trade-offs. If you don't refactor directories
often, then git's disability to detect this kind of conflict won't
matter much to you. git and svn don't address the same set of requirements.

Here's the script, you'll also need the svn-init.sh from the
tarball to run it:

  # $Id: svn-directories-move1-moved.sh 227 2008-08-24 14:39:21Z stsp $
  # NOTE: Modified to also change content inside the renamed directory
  . ./svn-init.sh
  # Move directory in trunk
  svn move $trunk/gamma $trunk/gamma.moved1
  svn commit -m "renamed gamma" $trunk
  # Also rename a file inside gamma.moved1
  svn move $trunk/gamma.moved1/delta $trunk/gamma.moved1/delta.moved
  svn commit -m "renamed delta" $trunk
  # Move the same directory to a different path in the branch
  svn move $branch/gamma $branch/gamma.moved2
  svn commit -m "renamed gamma, too" $trunk
  # Delete a file in gamma.moved2
  svn remove $branch/gamma.moved2/delta
  svn commit -m "removed gamma.moved2/delta" $branch
  # Committing here does not affect the merge result
  # Merge the move into the branch
  svn merge $trunk_url $branch

Received on 2009-06-16 14:11:23 CEST

This is an archived mail posted to the Subversion Users mailing list.