tags:

views:

430

answers:

4

In my local Subversion working copy, I have a copy of trunk and of a code branch. I've made changes in the trunk, and want to copy these changes to my (currently clean) local copy of the branch.

I know I can check in the code to trunk, then use svn merge to get the changes onto the branch, but is there some way of doing this without first checking the changes in?

Sadly, diff/patch won't work, as there are changes in the code surrounding my changes between trunk and branch. I know svn merge can cope with those, but as I say, I'd rather not have to check my changes in first.

Edited to add an example:

The trunk has a file containing the following:

File in trunk:                       File in branch:
apple                                apple
orange                               banana
pear                                 pear

In trunk, I add dragon fruit below pear in the trunk file on my working copy. Were I to check that change in and use merge to copy it to branch, Subversion would correctly add dragon fruit below pear in the branch version of the file.

svn diff on my copy of the trunk file produces something similar to the following:

Index: fruit.txt
===================================================================
--- fruit.txt  (revision 56)
+++ fruit.txt  (working copy)
@@ -1,3 +1,4 @@
 apple
 orange
 pear
+dragon fruit

Clearly using patch won't work, as it notices the difference between the non-changed texts.

What I want to happen, without having to check anything in, is to have dragon fruit listed after pear in both files, but not to have the orange/banana difference changed on either file.

+2  A: 

You could svn switch a copy of your working copy to the branch.

Your safest bet, though, is to commit your changes to a private branch and use svn merge to merge them wherever you need them.

moonshadow
But DO take a quick backup copy of what on your disk first. SVN switch tries its best, but there's no guarantees.
Jim T
svn switch looks to be the best option I have at the moment. It's far from ideal, but it'll have to do.
me_and
A: 

Neither switch nor merge nor diff solves your problem of having certain changes that you want to port over and certain changes that you don’t (assuming that the changes are within the same set of files; if they are in different files, you can port only the relevant files).

In any case, you will have to have some way to differentiate only the changeset that you want to apply to the branch, apply it, and then continue your additional modifications to trunk.

I would use WinMerge, TortoiseMerge, or some similar tool to compare the relevant files between branch and trunk, and step through it and apply only the changes you want.

Michael Hackner
I'm using TortoiseMerge at the moment, but as far as I can tell, that only offers a diff/patch method for moving the changes over; that won't work as the code in the branch has changed relative to the code in trunk. Unless you mean using something like TortoiseDiff/WinDiff to compare the differences and move them over manually…
me_and
A: 

If you don't mind it being in trunk temporarily, you could commit to trunk (rev 1234), immediately revert that change in trunk (svn merge -c-1234 => rev 1235), then merge the 1234 commit into the branch.

Chris J
A: 

The reason you cannot apply an svn diff patch is because the version of the code in the trunk must be more recent than the change in your trunk. This is a common scenario where you may have branched out to work on a feature and work continued on the trunk.

To solve this problem, you need to bring your branch up to date with the trunk, THEN apply the diff.

svn merge svn://path/to/trunk /path/to/working-copy

This will bring your branch up to date with the trunk. If there are any conflicts, you'll have to resolve them.

Now,

svn commit /path/to/working-copy -m "Merged latest trunk changes into the branch"

then,

svn diff /path/to/trunk > my-new-code.patch

and finally,

cd /path/to/working-copy patch -p0 -i /path/to/my-new-code.patch

Your working copy of the branch will now be up to date with the trunk, plus it will have your new changes... and the repository version of the trunk will not have been touched.

Edit: After the original question was edited to provide more information, I now suggest the following:

This is assuming, for instance, that the branch was created based on revision 30 of the trunk and that the change you want to import is in revision 56 of the trunk

  1. svn up /path/to/branch-WC
  2. svn up /path/to/trunk-WC -r 30
  3. svn merge svn://path/to/trunk -r 55:56 /path/to/trunk-WC
  4. cd /path/to/trunk-WC
  5. svn diff /path/to/trunk-WC > /path/to/branch-WC/mychange.patch
  6. cd /path/to/branch-WC
  7. patch -p0 -i mychange.patch

What you're doing here is updating the trunk to the same revision as where the branch was created. This way, any patches you produce will be based on the same revision.

Next, by merging revision 55:56, you are asking ONLY for the "dragon fruit" diff. Since the orange/banana change was NOT done between revision 55:56, that diff will not be entered into the patch file.

If the change in revision 56 depends on previous changesets, you might have to resolve some conflicts or merge some more revisions (since this revision 30 trunk won't know about them), but it should be exactly what you need.

Mike
This isn't an option, sadly. The branch in question was cut off from the trunk to provide a copy of the code at a specific shipped version. I'm making bug-fixes on the trunk which we want to back-apply and offer to the people who have the previous version without giving them all the new features on the trunk branch.
me_and