Subversion merges require a few things:
Common ancestry
You think this is a no brainer, but this happens quite a bit. I've seen developers who would create a branch using svn mkdir
, check out that branch, copy the files from the trunk into that branch, and then do a svn add
to add them back in.
Although the branch and the trunk had the same names and same structure, Subversion looked at them as two completely separate files. There's no common history between the trunk and that branch. Of course, the developer should have used svn cp
to copy the trunk to the branch.
However, you can have issues like this in smaller chunks. Imagine a developer makes a branch the correct way. Then discovers that some *.jpg
files are missing from the project. The developer checks out the branch, and adds the files. All taken care off. Now, the developer realizes that the same bug is also on trunk. No problem, checkout trunk add add the missing *.jpg
files.
Of course, the *.jpg
files on trunk don't share a common ancestry as the ones on the branch. The developer should have merged the revision where those *.jpgs
were created from the branch to the trunk.
Revision Collisions
Subversion doesn't merge branches: It merges changes. This is a tricky concept to understand, but it gives Subversion a lot of merging power.
I have a branch I created off of trunk on revision 100.
Revision history of branch
- 100: Created branch
- 103: Bugfix 2001
- 110: Merged trunk to branch
- 112: Made more changes
Revision history of trunk
- 102: Changes
- 104: Bugfix 2001
- 111: Changes
Now I want to merge my branch back to my trunk. If I don't specify revisions to use, Subversion tries to figure out which revisions I need to merge. I've never merged my branch to my trunk, so Subversion sees that last common ancestor between my branch and trunk is revision 100. It then sees that I need to merge changes 103, 110, and 112 back to my trunk.
However Revision 110 on my branch are the changes I've already merged to my trunk! If I am not careful, I'll be attempting to merge those changes back into my trunk causing conflicts.
Subversion is suppose to handle this, but not always so cleanly. Before running your merge, do the following command:
$ svn mergeinfo --showrevs eligible $URL/branches/branch
This will show the revisions that Subversion wants to merge to my trunk. I should look over that list and make sure those changes are not already on my trunk.
Let's say I took a look at this list, and realize that this eligible list contains revision 103, 110, and 112. Wait a second. Revision 103 fixes Bug 2001, but that's already been fixed on trunk. For some reason, Revision 110 is also listed, and Revision 110 is a merge of my trunk to my branch. I don't want this revision to be considered either.
What I need to do is to inform Subversion not to consider these revisions:
$ svn merge --record-only -c 103 -c 110 $URL/branches/branch
$ svn commit -m"Updating merge information to prevent collisions with 103 and 110"
Now, I run svn mergeinfo --showrevs eligible
again, these two revisions won't be listed. I've basically informed Subverison that these two sets of changes are already in my trunk.
You can always use --dry-run
to try out a merge before it is complete. Subversion merging always works if you specify the revisions you want to merge. Problems tend to happen when you try to get Subversion to track merging on its own. It's definitely better than it use to be, but Subversion can be confused with complicated circumstances. We had a project where branches were renamed, the trunk was replaced, and merging was done between trunk and two other branches. (Don't ask why.).
The developer was unable to do a merge because they ended up with a few hundred conflicts. Looking at the eligible revisions, I was able to clean up the mess, and get the merge working.
Remember to merge early and often: The more often you merge, the more likely the merge will work and any conflicts will be easy to find. Try to keep merging activity simple. If you fix a bug on two different branches, you need to let Subversion know via svn merge --record-only
.
Whatever you do. Don't panic. Conflicts will happen, and if you understand how to solve them, you can avoid merge hell.