views:

675

answers:

2

Hello,

Am trying to merge (from a branch) a file in a directory that does not yet exist on trunk. Here is the example:

Trunk (from which we branch)

/
/root1.txt
/foo/foo1.txt

Branch (after 2 checkins)

/
/root1.txt
/foo/foo1.txt
/bar/bar1.txt
/bar/bar2.txt

First checkin:

A  /bar
A  /bar/bar1.txt

Second checkin:

A  /bar/bar2.txt

Assuming the trunk hasn't changed, is it possible to get only /bar/bar2.txt into the trunk? Here are the solutions I have tried already:

svn merge -rX:X+1 /path/to/branch/bar .  --> nothing gets merged here
svn merge -rX+1:X+2 /path/to/branch/bar .  --> pulls bar2.txt into the trunk but not within bar directory
svn merge -rX:X+1 /path/to/branch .      --> pulls both directory and bar1.txt into trunk

svn copy /path/to/branch/bar .           --> recursively copies directory bar into trunk

mkdir /path/to/trunk/bar
svn add bar
svn merge -rX+1:X+2 /path/to/branch/bar bar/

The final solution here kind of works. It allows me to only pull in bar2.txt into the trunk and continue but when I try to reintegrate my branch back into trunk later, you then get tree conflicts on the directory (directory gets added in both places -> 'local add, incoming add upon merge').

I understand that if my team would do finer grain check ins - i.e. add the directory in a single commit and the files in another - then I could merge as I am trying to above. Is that the only solution?

  1. It seems like SVN allows you to merge individual files from a branch into the trunk so is it possible with individual dirctories (non-recursively)?
  2. In the partial solution I found above, can I mark the directory in the branch as merged to the trunk independently of the other files that were checked in at the same time so that I don't get the tree conflict?

Thanks!

A: 

Try this:

svn merge http://url/to/trunk/bar http://url/to/branch/bar bar/

It's easier if you think of all merge commands as simply applying a diff. Compare the output of svn help merge to svn help diff -- they're very similar. Once you have figured out the svn diff command that will produce exactly the changeset you need, apply that to the correct directory and you're set!

So in your case, what you need is the difference between bar/ on trunk and bar/ on the branch, applied to the local (trunk) version of bar.

Edit: and in the case where bar/ does not yet exist in trunk, a simple svn copy operation will do the trick:

svn copy http://url/to/branch/bar http://url/to/trunk/bar -m'merging new directory bar/'

(Note that the target is the svn repository itself, rather than the working copy.)

Ether
but how does this work if the directory 'bar' does not yet exist on the trunk - i.e. I need to figure out how to merge a single file from a directory on the branch when the directory doesn't yet exist in the trunk.
@oldnoakes: answer updated to cover that case.
Ether
A: 

The problem is that you committed the A bar in the same revision as A bar/bar1.txt.

I would revert to before the two commits. Then commit the A bar separately, then the A bar/bar1.txt then the A bar/bar2.txt. You should then be able to merge the desired individual revisions with the trunk.

Update: Maybe this document will allow you to do what you want. Seems a bit hackish to me though.

Mergeinfo, or more specifically the versioned property svn:mergeinfo, is the history of merges made into a given file or directory. This article gives a detailed look at mergeinfo; what it means and how it works.

gWiz
I agree but it isn't that simple if the branch has moved along significantly since the initial addition took place. I would have to roll back, do what you suggest, and then start re-applying subsequent checkins back on top of the branch.
Ack. I see. Updated answer.
gWiz