简体   繁体   中英

How do I resolve a SVN tree conflict

I have been reading for days now trying to find a way to resolve tree conflicts using tortiseSVN 1.8. I have two branch off of trunk:

  • branches/3.1
  • branches/3.2

Again, both of these branches were off of trunk. We do not do "mainline" development on trunk. I'm trying to merge the changes from our 3.1 branch to our 3.2 branch.

The code in 3.1 went through some refactoring and a lot of folders that exist in the 3.2 branch no longer exist in the 3.1 branch. Also, there is some new work adding new folder to 3.2. The problem is that a tree conflict does not give me a way to resolve the conflicts, but only allows me to accept the working copy. This seems like a serious flaw. We are doing a lot of refactoring and I'm looking for a process that we can integrate changes on an earlier release branch into a later release branch.

Can somebody tell me the best way to handle this?

For merging to work, you need two things:

  • You need a common ancestry between the two branches.
  • If you place on keeping the two branches, in sync, you need to do regular merging between the two. For example, I assume that all work on 3.1 should be in 3.2. As you do work in both branches, you should have been merging your 3.1 changes into 3.2.

Merge conflicts happen because merging is a three-way comparison. The two development streams (a development stream can refer to a branch or trunk) are compared to each other, and they're compared to their last common ancestor. Imagine a file where line #100 was changed in both development streams. A merge from one to the other will result in a conflict.

Subversion doesn't just diff files, it diffs directories too. If I rename a file in one development steam (or move it), and I do a merge, it will be renamed (or moved) in the other development stream. If I delete or add a file in one development stream, and merge, it will be deleted or added in the other development stream too.

In Subversion, a tree conflict can happen if I do two different things to the same file on the two development streams. For example, I rename the file on both the 3.1 and 3.2 branch. Even if I rename them the same name, Subversion will pick it up as a conflict.


To prevent your disaster from happening again: Make sure that your two branches do share the same ancestry. Why not branch 3.2 from the 3.1 branch, or at least reintegrate the 3.1 branch back into trunk before branching 3.2. Subversion usually is pretty good at following history, but you need to make sure that the branches share a common history.

The other is regular merging. You need to merge 3.1 to the 3.2 branch on a regular basis -- maybe even every day. This makes sure that people working on the 3.2 branch have the changes they need in 3.1 and aren't duplicating the work. Constant merging also keeps the changes small, and when there are merge conflicts they're much easier to handle. Remember the svn mergeinfo command which can let you know what's already been merged into 3.2 and what on 3.1 still needs to be merged. You can always use the --record-only parameter to prevent a particular revision from being considered for a future merge. For example, you fix a bug on both branches, you use --record-only to make sure that the fix on 3.1 isn't done on 3.2. Or, if you made a change in 3.1 you don't want on 3.2, doing a --record-only will prevent you from considering that change on the 3.2 branch the next merge.


What to do now? You need to untangle your work. Look at a svn log between the two branches. If you see a bugfix taking place on both branches, use a svn merge --record-only to let Subversion know that a particular change on the 3.1 branch was also done (albeit manually) on the 3.2 branch. Look at file moves and renames and see how they were done on each branch.

Once you've done that, merge changes on 3.1 to 3.2 a few revisions at a time, cherry pick merges. Make sure that a change on 3.1 is something you want on 3.2.

This is a long draw out process, but you it needs to be done. Use this as a lesson to improve your development process.


We use to use what sounds like a similar system you used. Trunk was suppose to be pristine and match our releases (it never really did). We kept losing changes from one release to another because of when we made a new branch and when we merged the previous branch to trunk (or we simply lost where we branched from).

Branching is like children: You make one, and you better be ready to take care of it and not lose track where it goes.

We switched to a continuous development process . We do our development on trunk, and then branch right before we do a release. The branch point usually comes around the time when we finished all of the features for that release, and we are now in a process of bug fixing.

The release is done on the branch. If we find a bug, we will fix the bug on the branch, and then only merge that revision to the trunk (if that bug is also on the trunk). Once a release is done, the branch is locked. If we need to do a hotfix, we can reuse that branch for the hotfix.

Occasionally, we have feature branches . When we do, I make sure that we are constantly merging from the development stream to that feature branch. This way, when we finally reintegrate that feature back into trunk, we have few if any conflicts.

By keeping branching to a minimum and by tracking where we branch from, and doing constant merges (like in a feature branch), we have reduced merge conflicts, and no longer have the issues that once plagued our releases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM