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

Re: Merge branch from trunk into newer branch from trunk, resolving directory conflicts

From: Stefan Sperling <stsp_at_elego.de>
Date: Sun, 5 Dec 2010 11:28:46 +0100

On Thu, Dec 02, 2010 at 01:50:09AM -0500, derek fong wrote:
> Hello,
>
> Here's my scenario, hope someone can help me out with it:
>
> I created a branch (b1) from trunk several months ago. Since then, my branch has undergone active development while the trunk has undergone a couple of relatively minor revisions.
>
> My team later created another branch off of trunk several weeks after mine (b2), and began refactoring code... directories got moved around, and files got added, renamed and deleted on this new branch.
>
> I now want to merge the changes I've made on my branch (b1) to my team's branch (b2) so that we can all resume working on the same branch (b2) with my changes merged into theirs, but am not quite sure how to go about this. I obtained the revision number of trunk when I created my branch (r500), then proceeded to do a three-way merge that looked something like this:
>
> % svn checkout repo/branches/b2
> % cd b2
> % svn merge repo/trunk_at_500 repo/branches/b1_at_HEAD .
>
> This appears to work at first, but since some directories have been moved + removed from b2 and some of my work on b1 occurred in one of these deleted directories, Subversion throws the following conflict on the directory ("application") that was deleted from b2 during the refactoring:
>
> [fong_at_localhost] ~/sandbox/temp/_merged/repo: svn stat
> C .
> ? dir_conflicts.prej
> ! C application
> > local delete, incoming edit upon merge
>

Subversion's merge algorithm assumes that the tree structure of the
merge source matches that of the merge target. If they don't,
differences show up as adds or deletes. Those get flagged as conflicts
to make you aware of the problem. There is no way Subversion can resolve
these conflicts automatically at the moment. You will have to resolve
them manually.

Basically, your collegues should not have done refactoring on an
isolated branch. It needs to be done on all branches at once, or on a
branch that all other branches will then immediately sync to.
We know that this is a big limitation, and are working towards making
Subversion handle these cases better. But it will still take a couple
of releases until Subversion gets there.

Right now, Subversion will only detect (most) of these conflicts,
but will (in general) not auto-resolve them.
To find out more about the basics of tree conflicts read the book at:
http://svnbook.red-bean.com/nightly/en/svn.tour.treeconflicts.html

> I think I understand why that's happening, but what's the best way for
> me to retain the history of the files in "application" that are now
> scheduled for deletion following the merge? Do I need to accept
> "application" as deleted, then manually "svn copy" files and
> directories from b1 into their new refactored locations on b2? It
> seems there should be a better way to do this, but I'm stumped.

The basic steps are:
 For each tree conflict:
   1) Understand why the conflict occured
   2) Figure out what you want the merge result to be
   3) Figure out how to get your merge target working copy into the
      desired state

I would refrain from using "copy" to pull changes across branches.
Use svn merge instead.
Assume you determine in step 2) that your changes within "applications"
should be applied to another directory because "applications" was
renamed on the b2 branch. You can do "subtree merges" to merge subtrees
into different destinations:
 % svn merge repo/trunk/foo_at_500 repo/branches/b1/foo_at_HEAD bar/

This will merge changes made within directory foo into directory bar of
your working copy of b2. This will of course assume that the tree structures
beneath foo/ and bar/ match up.

You can also do this for individual files:
 % svn merge repo/trunk/file.txt_at_500 repo/branches/b1/file.txt_at_HEAD newfile.txt

Once you've done such a subtree merge, you should see your changes at
the new location, and you can run "svn resolve" on the old location to
mark the tree conflict as resolved.
You can also start again with a clean working copy and perform several
merges in a manner that doesn't create tree conflicts. This will save
you from having to run "svn resolve" and is a better approach when there
are many tree conflicts caused by a merge.
Remember that it's always safe to start over by running "svn revert -R ."
on the working copy that you're merging into. Nothing gets committed
unless you run "svn commit".

You will see subtree mergeinfo being created by your subtree merges.
This is mostly harmless, but should in general be avoided by designing
your branching/merging strategy such that you will always merge into the
logical roots of branches. However you've already passed the point where
you can avoid subtree mergeinfo comfortably. I'd recommend just leaving
mergeinfo alone and let Subversion do its thing.
See http://www.collab.net/community/subversion/articles/merge-info.html
for in-depth information about mergeinfo.

In the future, merge refactorings into branch roots right away.
If the branches are destined to be merged, they eventually need to agree
on the same tree structure anyway. There will probably always be conflicts,
but they'll be easier to manage if the timing is right.

Good luck,
Stefan
Received on 2010-12-05 11:29:30 CET

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

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.