You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@subversion.apache.org by "Wilks, Dan" <dw...@intacct.com> on 2014/07/26 00:57:28 UTC

Merging, Cherry-Picking, Adding Files and Tree Conflicts

I'm getting an unexpected conflict when trying to refresh a branch from the trunk after having a) merged that branch back to the trunk; b) continued bug fixing on that branch and cherry-picking those changes to the trunk; c) adding a file on the branch and having that file cherry-picked to the trunk.  Now when I try to refresh my branch from the trunk the newly added file is causing issues.

If, however, I never reintegrate the branch into the trunk and simply cherry-pick from the branch to the trunk then the newly added file doesn't seem to cause any damage.

I'm wondering a) what did I do wrong to cause it and b) now that it has happened is there any way to make svn realize that the new file is really the same file so that future merges won't have issues.

Client:
svn, version 1.8.9 (r1591380)
   compiled May 15 2014, 11:09:48 on x86_64-apple-darwin12.5.0

Server:
svnserve, version 1.6.11 (r934486)
   compiled Apr 11 2013, 16:13:51

Below is a script that illustrates the problem. 


Thanks,
Dan

####

#Setup
brancha=brancha
branchb=branchb

brancha_svn_url=http/example.svn.com/svn/branches/$brancha
branchb_svn_url=http/example.svn.com/svn/branches/$branchb

# Make a new branch and populate it with some files
mkdir $brancha
echo file1 >> $brancha/file1
echo file2 >> $brancha/file2
echo file3 >> $brancha/file3
svn import $brancha/ $brancha_svn_url -m"Initial revision"
# Make a branch of our new branch
r0=`svn cp $brancha_svn_url $branchb_svn_url -m"creating test branch" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'`
echo $branchb created, revision $r0

# Check out the new branches
rm -rf $brancha/
svn co $brancha_svn_url
svn co $branchb_svn_url

# Make some non-conflicting modifications to both branches
echo $branchb-1 >> $branchb/file1
cd $branchb && svn commit -m"check in $branchb/file1" && cd ..
echo $brancha-2 >> $brancha/file2
cd $brancha && svn commit -m"check in $brancha/file2" && cd ..

# Merge $branchb into $brancha after updating it from $brancha
cd $branchb && svn update && svn merge ^/branches/$brancha && svn commit -m"merge from $brancha" && cd ..
cd $brancha && svn update && svn merge ^/branches/$branchb && svn commit -m"Merge from $branchb" && cd ..
cd $branchb && svn update && svn merge ^/branches/$brancha && svn commit -m"merge from $brancha" && cd ..

# Now make somre more changes on both branches one of which adds a new file to $branchb
echo $branchb-3 >> $branchb/file1 && cd $branchb && r3=`svn commit -m"change to $branchb/file1" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
echo Committed revision $r3
echo $brancha-4 >> $brancha/file2 && cd $brancha/ && r4=`svn commit -m"change to $brancha/file2" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
echo Committed revision $r4
echo $branchb-5 >> $branchb/file4 && cd $branchb && svn add file4 && r5=`svn commit -m"added $branchb/file4" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
echo Committed revision $r5
echo $branchb-6 >> $branchb/file3 && cd $branchb && r6=`svn commit -m"change to $branchb/file3" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
echo Committed revision $r6

# And cherry-pick the $branchb changes back to $brancha
cd $brancha && svn update && svn merge -c $r6 ^/branches/$branchb && svn commit -m"cherry-pick rev $r6 from $branchb/file3" && cd ..
cd $brancha && svn update && svn merge -c $r5 ^/branches/$branchb && svn commit -m"cherry-pick rev $r5 from $branchb/file4" && cd ..
cd $brancha && svn update && svn merge -c $r3 ^/branches/$branchb && svn commit -m"cherry-pick rev $r3 from $branchb/file1" && cd ..

# Now try to freshen branch b
cd $branchb && svn update && svn merge ^/branches/$brancha

--- Merging r229 through r236 into '.':
U    file2
   C file4
--- Recording mergeinfo for merge of r229 through r236 into '.':
 U   .
Conflict discovered when trying to add 'file4'.
An object of the same name already exists.
Select: (mf) my version, (tf) their version, (p) postpone,
        (q) quit resolution, (h) help: q


#####

Now we do it all again, this time without the first set of changes & merges, just the cherry-picking that seemed to cause issues above.

# Cleanup
svn rm $brancha_svn_url -m"cleanup test branch"
svn rm $branchb_svn_url -m"cleanup test branch"
rm -rf $brancha/ $branchb/


# Make a new branch and populate it with some files
mkdir $brancha
echo file1 >> $brancha/file1
echo file2 >> $brancha/file2
echo file3 >> $brancha/file3
svn import $brancha/ $brancha_svn_url -m"Initial revision"
# Make a branch of our new branch
r0=`svn cp $brancha_svn_url $branchb_svn_url -m"creating test branch" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'`
echo $branchb created, revision $r0

# Check out the new branches
rm -rf $brancha/
svn co $brancha_svn_url
svn co $branchb_svn_url

# Now make somre more changes on both branches one of which adds a new file to $branchb
echo $branchb-3 >> $branchb/file1 && cd $branchb && r3=`svn commit -m"change to $branchb/file1" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
echo Committed revision $r3
echo $brancha-4 >> $brancha/file2 && cd $brancha/ && r4=`svn commit -m"change to $brancha/file2" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
echo Committed revision $r4
echo $branchb-5 >> $branchb/file4 && cd $branchb && svn add file4 && r5=`svn commit -m"added $branchb/file4" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
echo Committed revision $r5
echo $branchb-6 >> $branchb/file3 && cd $branchb && r6=`svn commit -m"change to $branchb/file3" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
echo Committed revision $r6

# And cherry-pick the $branchb changes back to $brancha
cd $brancha && svn update && svn merge -c $r6 ^/branches/$branchb && svn commit -m"cherry-pick rev $r6 from $branchb/file3" && cd ..
cd $brancha && svn update && svn merge -c $r5 ^/branches/$branchb && svn commit -m"cherry-pick rev $r5 from $branchb/file4" && cd ..
cd $brancha && svn update && svn merge -c $r3 ^/branches/$branchb && svn commit -m"cherry-pick rev $r3 from $branchb/file1" && cd ..

# Merge the $branchb creation into $brancha so we can attempt to freshen $branchb from $brancha
cd $brancha && svn update && svn merge -c $r0 ^/branches/$branchb && svn commit -m"cherry-pick rev $r0 ($branchb creation)" && cd ..


# Now try to freshen branch b
cd $branchb && svn update && svn merge ^/branches/$brancha




Re: Merging, Cherry-Picking, Adding Files and Tree Conflicts

Posted by Stefan Sperling <st...@elego.de>.
On Fri, Jul 25, 2014 at 10:57:28PM +0000, Wilks, Dan wrote:
> I'm getting an unexpected conflict when trying to refresh a branch from the trunk after having a) merged that branch back to the trunk; b) continued bug fixing on that branch and cherry-picking those changes to the trunk; c) adding a file on the branch and having that file cherry-picked to the trunk.  Now when I try to refresh my branch from the trunk the newly added file is causing issues.
> 
> If, however, I never reintegrate the branch into the trunk and simply cherry-pick from the branch to the trunk then the newly added file doesn't seem to cause any damage.
> 
> I'm wondering a) what did I do wrong to cause it and b) now that it has happened is there any way to make svn realize that the new file is really the same file so that future merges won't have issues.
> 
> Client:
> svn, version 1.8.9 (r1591380)
>    compiled May 15 2014, 11:09:48 on x86_64-apple-darwin12.5.0
> 
> Server:
> svnserve, version 1.6.11 (r934486)
>    compiled Apr 11 2013, 16:13:51
> 
> Below is a script that illustrates the problem. 
> 
> 
> Thanks,
> Dan

Hi Dan,


have you already tried blocking the cherry-picked brancha changes from
entering branchb?
http://svnbook.red-bean.com/en/1.7/svn.branchmerge.advanced.html#svn.branchmerge.advanced.blockchanges

On $branchb you'd want to block the revisions resulting from the
following merges in your script:

cd $brancha && svn update && svn merge -c $r6 ^/branches/$branchb && svn commit -m"cherry-pick rev $r6 from $branchb/file3" && cd ..
cd $brancha && svn update && svn merge -c $r5 ^/branches/$branchb && svn commit -m"cherry-pick rev $r5 from $branchb/file4" && cd ..
cd $brancha && svn update && svn merge -c $r3 ^/branches/$branchb && svn commit -m"cherry-pick rev $r3 from $branchb/file1" && cd ..

This seems to be a similar situation as described here:
http://svnbook.red-bean.com/en/1.7/svn.branchmerge.advanced.html#svn.branchmerge.advanced.reintegratetwice
"If you now try to merge outstanding changes from trunk to your branch,
Subversion will consider changes made in revision X as eligible for merging
into the branch. However, since your branch already contains all the changes
made in revision X, merging these changes can result in spurious conflicts! "

Since you're cherry-picking between branches, the 'automatic' merge in
Subversion 1.8 will no longer be able to handle this automatically.
http://subversion.apache.org/docs/release-notes/1.8.html#auto-reintegrate
"For best results, it is recommended to always merge all eligible revisions,
i.e. not using the -r or -c options of svn merge. Merging just a subset of
eligible revisions increases the likelihood of problems during future merges."

> 
> ####
> 
> #Setup
> brancha=brancha
> branchb=branchb
> 
> brancha_svn_url=http/example.svn.com/svn/branches/$brancha
> branchb_svn_url=http/example.svn.com/svn/branches/$branchb
> 
> # Make a new branch and populate it with some files
> mkdir $brancha
> echo file1 >> $brancha/file1
> echo file2 >> $brancha/file2
> echo file3 >> $brancha/file3
> svn import $brancha/ $brancha_svn_url -m"Initial revision"
> # Make a branch of our new branch
> r0=`svn cp $brancha_svn_url $branchb_svn_url -m"creating test branch" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'`
> echo $branchb created, revision $r0
> 
> # Check out the new branches
> rm -rf $brancha/
> svn co $brancha_svn_url
> svn co $branchb_svn_url
> 
> # Make some non-conflicting modifications to both branches
> echo $branchb-1 >> $branchb/file1
> cd $branchb && svn commit -m"check in $branchb/file1" && cd ..
> echo $brancha-2 >> $brancha/file2
> cd $brancha && svn commit -m"check in $brancha/file2" && cd ..
> 
> # Merge $branchb into $brancha after updating it from $brancha
> cd $branchb && svn update && svn merge ^/branches/$brancha && svn commit -m"merge from $brancha" && cd ..
> cd $brancha && svn update && svn merge ^/branches/$branchb && svn commit -m"Merge from $branchb" && cd ..
> cd $branchb && svn update && svn merge ^/branches/$brancha && svn commit -m"merge from $brancha" && cd ..
> 
> # Now make somre more changes on both branches one of which adds a new file to $branchb
> echo $branchb-3 >> $branchb/file1 && cd $branchb && r3=`svn commit -m"change to $branchb/file1" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
> echo Committed revision $r3
> echo $brancha-4 >> $brancha/file2 && cd $brancha/ && r4=`svn commit -m"change to $brancha/file2" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
> echo Committed revision $r4
> echo $branchb-5 >> $branchb/file4 && cd $branchb && svn add file4 && r5=`svn commit -m"added $branchb/file4" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
> echo Committed revision $r5
> echo $branchb-6 >> $branchb/file3 && cd $branchb && r6=`svn commit -m"change to $branchb/file3" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
> echo Committed revision $r6
> 
> # And cherry-pick the $branchb changes back to $brancha
> cd $brancha && svn update && svn merge -c $r6 ^/branches/$branchb && svn commit -m"cherry-pick rev $r6 from $branchb/file3" && cd ..
> cd $brancha && svn update && svn merge -c $r5 ^/branches/$branchb && svn commit -m"cherry-pick rev $r5 from $branchb/file4" && cd ..
> cd $brancha && svn update && svn merge -c $r3 ^/branches/$branchb && svn commit -m"cherry-pick rev $r3 from $branchb/file1" && cd ..
> 
> # Now try to freshen branch b
> cd $branchb && svn update && svn merge ^/branches/$brancha
> 
> --- Merging r229 through r236 into '.':
> U    file2
>    C file4
> --- Recording mergeinfo for merge of r229 through r236 into '.':
>  U   .
> Conflict discovered when trying to add 'file4'.
> An object of the same name already exists.
> Select: (mf) my version, (tf) their version, (p) postpone,
>         (q) quit resolution, (h) help: q
> 
> 
> #####
> 
> Now we do it all again, this time without the first set of changes & merges, just the cherry-picking that seemed to cause issues above.
> 
> # Cleanup
> svn rm $brancha_svn_url -m"cleanup test branch"
> svn rm $branchb_svn_url -m"cleanup test branch"
> rm -rf $brancha/ $branchb/
> 
> 
> # Make a new branch and populate it with some files
> mkdir $brancha
> echo file1 >> $brancha/file1
> echo file2 >> $brancha/file2
> echo file3 >> $brancha/file3
> svn import $brancha/ $brancha_svn_url -m"Initial revision"
> # Make a branch of our new branch
> r0=`svn cp $brancha_svn_url $branchb_svn_url -m"creating test branch" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'`
> echo $branchb created, revision $r0
> 
> # Check out the new branches
> rm -rf $brancha/
> svn co $brancha_svn_url
> svn co $branchb_svn_url
> 
> # Now make somre more changes on both branches one of which adds a new file to $branchb
> echo $branchb-3 >> $branchb/file1 && cd $branchb && r3=`svn commit -m"change to $branchb/file1" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
> echo Committed revision $r3
> echo $brancha-4 >> $brancha/file2 && cd $brancha/ && r4=`svn commit -m"change to $brancha/file2" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
> echo Committed revision $r4
> echo $branchb-5 >> $branchb/file4 && cd $branchb && svn add file4 && r5=`svn commit -m"added $branchb/file4" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
> echo Committed revision $r5
> echo $branchb-6 >> $branchb/file3 && cd $branchb && r6=`svn commit -m"change to $branchb/file3" | grep Committed | sed -e 's/Committed revision \(.*\)\./\1/'` && cd ..
> echo Committed revision $r6
> 
> # And cherry-pick the $branchb changes back to $brancha
> cd $brancha && svn update && svn merge -c $r6 ^/branches/$branchb && svn commit -m"cherry-pick rev $r6 from $branchb/file3" && cd ..
> cd $brancha && svn update && svn merge -c $r5 ^/branches/$branchb && svn commit -m"cherry-pick rev $r5 from $branchb/file4" && cd ..
> cd $brancha && svn update && svn merge -c $r3 ^/branches/$branchb && svn commit -m"cherry-pick rev $r3 from $branchb/file1" && cd ..
> 
> # Merge the $branchb creation into $brancha so we can attempt to freshen $branchb from $brancha
> cd $brancha && svn update && svn merge -c $r0 ^/branches/$branchb && svn commit -m"cherry-pick rev $r0 ($branchb creation)" && cd ..
> 
> 
> # Now try to freshen branch b
> cd $branchb && svn update && svn merge ^/branches/$brancha
> 
>