4
votes

As far as I understand, the most common (and recommended) way to handle branching & merging in Subversion is:

  • create branch as a copy of trunk
  • do disruptive development on branch, and regular development on trunk
  • While doing so, regularly merge changes trunk -> branch, to avoid the branch diverging too much. With merge tracking (svn:mergeinfo), I can just run svn merge ^/trunk, and SVN will automatically fetch all unmerged changes from trunk.
  • Once the work on the branch is done, merge everything back (on trunk: svn merge --reintegrate ^/branch/foo), then discard branch.

(described e.g. in the SVN book, chapter Basic Merging).

Now my problem: While this works well for "feature branches", one sometimes also needs "release branches", which represent shipping/about to ship versions.

With release branches, in my experience merging has to happen in both directions:

  • bug fixes from the release branch must be merged into trunk (branch -> trunk)
  • but sometimes a bug fix from trunk (or even a new feature) is deemed critical for a release version (or an update to the release), and must therefore be merged trunk -> branch

I have not found anything firm on how SVN and svn:mergeinfo will handle this. Can I merge in both directions ("bidirectional merge"), and still have svn keep track of merged revisions?

Are there any pitfalls? Anything special to pay attention to?

2

2 Answers

2
votes

Can I merge in both directions ("bidirectional merge"), and still have svn keep track of merged revisions?

Yes, you can merge individual features (by merging specific revisions), and SVN will keep track of that.

2
votes

Actually merging in both direction in SVN often causes much more pain (as compared to git). The problem is that if you merge trunk into branch and then later try to merge the changes on the branch back into trunk, SVN will try to merge the changes from trunk which were merged into the branch again which will cause many unnecessary conflicts. To work around the issue, you can "record-only" the commit(s) where you merged the trunk into branch before merging the branch into trunk. See Advanced Merging - Blocking Changes chapter in the SVN book for a general approach (but the sample they provide is not for that particular use case).

Example:

  1. Assume your merge of the trunk into branch created two commits r3857 and r3858 (I see that often when using NetBeans, it first creates directories and then the files).
  2. Then you did some additional fixes on that release branch.
  3. Now you want to merge it back into trunk. Before doing that do the following in your trunk directory:

    svn merge "^/project/branches/release-0.1" -r3857:3858 --record-only

  4. After that merge from the release-0.1 branch as usual. That will result in a lower number of conflicts as compared to a direct merge attempt.

  5. Before committing I sometimes revert some of the introduced changes (in particular SVN might for some reasons introduce svnmerginfo at file level when there are resolved tree conflicts).