I have been using TortoiseSVN, svn, and subclipse and I think I understand the basics, but there's one thing that's been bugging me for a while: Merging introduces unwanted code. Here's the steps.
trunk/test.txt@r2
. A test file was created with 'A' and a return:
A
[EOF]
branches/TRY-XX-Foo/test.txt@r3
. Branched out the trunk
to TRY-XX-Foo
:
A
[EOF]
branches/TRY-XX-Foo/test.txt@r4
. Made an unwanted change in TRY-XX-Foo
and committed it:
A
B (unwanted change)
[EOF]
branches/TRY-XX-Foo/test.txt@r5
. Made an important bug fix in TRY-XX-Foo
and committed it:
A
B (unwanted change)
C (important bug fix)
[EOF]
Now, I would like to merge only the important bug fix back to trunk. So, I run merge for revision 4:5
. What I end up in my working directory is a conflict.
trunk/test.txt
:
A
<<<<<<< .working
=======
B (unwanted change)
C (important bug fix)
>>>>>>> .merge-right.r5
[EOF]
Against my will, Subversion has now included "unwanted change" into the trunk code, and I need to weed them out manually. Is there a way to merge only specified revisions when multiple consecutive changes are made in the branch?
The part of the problem is that B (unwated change) is included in .merge-right and I can't tell the difference between which revision it came from. I usually use TortoiseMerge and here's how it looks.
Merging only revisions 4,7, and 11-15 with svnmerge:
svnmerge.py merge -r4,7,11-15
And with regular svn:
svn merge -c4,7 -r10:15 http://.../branches/TRY-XX-Foo
The problem is that both svn
A
<<<<<<< .working
=======
B (unwanted change)
C (important bug fix)
>>>>>>> .merge-right.r341
and TortoiseSVN is treating the situation as 2-way merge. I've heard of the term 3-way merge, so I gave Beyond Compare a shot. With quick set up with TortoiseSVN, Edit Conflict now bring up the following screen. This is not perfect, since it's still requiring human intervention, but at least I can tell which changes are coming from where.
See screenshot.
I believe you are including the revisions you want correctly, but the merge algorithm is failing to find the place to insert the wanted change and so including the line above it also. Here are the same steps but with a different set of changes, and I believe it works as you expected originally:
$ svnadmin create repo $ svn mkdir -m '' file://`pwd`/repo/trunk Committed revision 1. $ svn mkdir -m '' file://`pwd`/repo/branches Committed revision 2. $ svn co file://`pwd`/repo/trunk co.trunk Checked out revision 2. $ cat > co.trunk/test.txt << EOF > A > B > C > EOF $ svn add co.trunk/test.txt A co.trunk/test.txt $ svn commit -m '' co.trunk Adding co.trunk/test.txt Transmitting file data . Committed revision 3. $ svn copy -m '' file://`pwd`/repo/trunk file://`pwd`/repo/branches/testbr Committed revision 4. $ svn co file://`pwd`/repo/branches/testbr co.testbr A co.testbr/test.txt Checked out revision 4. $ cat > co.testbr/test.txt << EOF > A > A1 unwanted > B > C > EOF $ svn commit -m '' co.testbr Sending co.testbr/test.txt Transmitting file data . Committed revision 5. $ cat > co.testbr/test.txt << EOF > A > A1 unwanted > B > B1 wanted > C > EOF $ svn commit -m '' co.testbr Sending co.testbr/test.txt Transmitting file data . Committed revision 6. $ svn merge -r 5:6 file://`pwd`/repo/branches/testbr co.trunk --- Merging r6 into 'co.trunk': U co.trunk/test.txt $ cat co.trunk/test.txt A B B1 wanted C
Well to clarify a thing about merge is that it actually has 2 steps.
So that means that after your merge is done, you can do a manual diff against head and the other branch to make sure that the merge was correct. And if something was wrong with it, like in your case, you can manually fix it before the commit.
/Johan
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With