I have source files managed in SVN using TortoiseSVN. I had added files and committed them to a revision, and subsequently decided to branch. I branched with the files I needed, and performed a delete on the trunk of the files that wasn't intended to be used.
Now I'm attempting to reintegrate the branch to the main trunk.
Using tortoise, I have merged from trunk to branch the range of revisions from AFTER the delete on the trunk to head. This brings the branch up to date.
Now I switch to the trunk, and attempt to merge the revisions from the branch to the trunk, and the merge indicates new files being "skipped" or the deletion of my files which are now complete.
Am I missing something on the merging to being the trunk up to date?
In order to do a reintegration, you need to merge ALL revisions from Trunk
that occurred after you branched into the branch you're looking to reintegrate.
Below is an example:
- Prev revs ...
- Rev 20 - (Trunk) Commit new files
- Rev 21 - (Feature Branch) Create feature branch
- Rev 22 - (Trunk) Delete files from Rev 20
- Rev 23 - (Trunk) Work on random files
- Rev 24 - (Feature Branch) Work on other random files
- Rev 25 - (Feature Branch) Merge revisions 22 and 23 into Feature Branch
- Rev 26 - (Trunk) Reintegrate Feature Branch into Trunk
You'll note that we included the deletion of your files (Rev 22) as part of the merge to Feature Branch (Rev 25).
Now this creates a new problem for you:
Your files that you desire to have in your Feature Branch
will be deleted when you merge in changes from Trunk
during Rev 25. This is true and accurate regarding what actually happened in the Trunk
. You will have several options here:
- If the files that were deleted in
Trunk
were modified in Feature Branch
during Rev 24, you'll receive a Tree Conflict when attempting to merge as per Rev 25. You can simply mark the conflict as resolved using your local changes when performing the merge.
- Perform a record-only merge of Rev 22 into
Feature Branch
and then subsequently perform any other merges necessary into Feature Branch
(this should be equivalent to what I mentioned in #1)
- Perform the merge into
Feature Branch
as per Rev 25. When the merge is complete, you can view the log of Feature Branch
and revert the changes made in Rev 25 (the merge itself) which deleted your files by cherry picking the files and reverting each one. These reversions will restore the files as new to be added to the repository of Feature Branch
. Note that these files will NOT be the same in the history as the original files. These are considered brand new files as far as SVN is concerned so they do not share any ancestry with their original counterparts.
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.