32

I have a client who insisted that we keep our new development separate from the main branches for the entirety of 2016. They had 3-4 other teams working on the application in various capacities. Numerous large changes have been made (switching how dependency injection is done, cleaning up code with ReSharper, etc). It has now fallen on me to merge main into our new dev branch to prepare to push our changes up the chain.

On my initial merge pull, TFS reported ~6500 files with conflict resolution. Some of these will be easy, but some of them will be much more difficult (specifically some of the javascript, api controllers, and services supporting these controllers).

Is there an approach I can take that will make this easier for me?

To clarify, I expressed much concern with this approach multiple times along the way. The client was and is aware of the difficulties with this. Because they chose to short on QA staff (1 tester for 4 devs, no automated testing, little regression testing), they insisted that we keep our branch isolated from the changes in the main branch under the pretense that this would reduce the need for our tester to know about changes being made elsewhere.

One of the bigger issues here is an upgrade to the angular version and some of the other third party softwares --unfortunately we have no come up with a good way to build this solution until all the pieces are put back into place.

  • 63
    Nope. You have two separate branches that were actively developed for a year. The merge is going to suck. – 17 of 26 Jan 3 '17 at 17:46
  • 2
    What is the extent of the changes that your team made? It may be more efficient to identify those changes and then manually reapply them to the current master codebase. – kdgregory Jan 3 '17 at 17:54
  • 2
    Is it the entirety of 2015 or 2016? If its 2015 its 2 years, which means it will double suck. – David Grinberg Jan 3 '17 at 22:53
  • 1
    Why does the client care if the work you're doing for them is on a separate branch in your version control system? – Ixrec Jan 4 '17 at 0:00
  • 17
    Whatever you do, make sure you're billing hourly. – Sean McSomething Jan 4 '17 at 17:18
37

There would have been a simple way which had kept your new development separate from the main branch without bringing you into this unfortunate situation: any change from the trunk should have been merged into your dev branch on a daily basis. (Was your client really so shortsighted that he could not anticipate that your branch needs to be remerged back into the main line some day?)

Anyway, best approach is IMHO trying to redo what should have happened on first hand:

  • identify the semantics of the changes on the main line for day 1 after the branch was created. Apply them to your current code base as well as you can. If it was a "local change", it should be simple, if it was a "cross cutting refactoring" like renaming a widely used class, apply it in a semantically equivalent manner to your current code base. Hopefully during that year no contradictory cross-cutting changes in the code base were made on "your" branch, otherwise this can become a real brain-teaser
  • test the result (did I mention you need a good test suite for this task)? Fix all bugs revealed by the test
  • now repeat this process for the changes on the main line for day 2, then day 3, and so on.

This might work when the teams strictly obeyed to the classic rules of version control ("only commit compilable, tested states" and "check in early and often").

After 365 repetitions (or 250, if you are lucky and you can bundle the work for weekend changes), you will be almost finished (almost, because you need to add the number of changes which will happen to the main line during the integration period). The final step will be to merge the updated dev branch into the trunk again (so you don't loose the trunk's history). This should be easy, because technically it should be only a replacement of the affected files.

And yes, I am serious, there is probably no shortcut to this. It might turn out that "daily portions" might be sometimes too small, but I would not expect this, I guess it is more likely daily portions can turn out beeing too big. I hope your client pays you really well for this, and that this is so expensive for him that he will learn from his failure.

I should add that you can try this also with switched sides - reintegrating the changes from your branch in small portions to the main line. This might be simpler when on your dev branch there were much fewer changes than on the trunk, or most of the changes happened in new source files which are currently not part of the trunk. One can see this as "porting" a feature from a product A (the dev branch) to a somewhat different product B (current state of the trunk). But if the majority of cross-cutting refactorings were done on the main line, and they affect your new code (the 6500 merge collisions seem to be some evidence for this), it might be easier the way I described it first.

  • 9
    If you're continuing development on the trunk during re-integration I suggest you branch the trunk tip first and develop from that. Otherwise you are effectively merging the past and the future simultaneously. But I defer to Doc Brown on any space-time discontinuities, naturally. – radarbob Jan 4 '17 at 0:56
  • 1
    @radarbob: what you suggest makes only sense if the OP integrates from dev to trunk, but not when he decides to merge from trunk to dev, as I described it first. If the OP transfers changes from trunk to his dev branch day-by-day (starting with changes 365 days in the past), it won't matter if development on the trunk goes on. He will just have to continue this tactics until he reaches the present (assumed he can integrate & test the changes of those 3-4 teams on one day in less than one day). – Doc Brown Jan 4 '17 at 6:47
  • Quote: "I should add that you can try this also with switched sides - reintegrating the changes from your branch in daily bundles to the main line." My spidey sense is blowing a fuse. I sense a potential cascade of "harmonic resonance distortion" with conflicting change integrations. – radarbob Jan 4 '17 at 13:52
  • This is good advice. See edit to address a couple of things here. – user258451 Jan 4 '17 at 17:20
  • 1
    @user258451: so you had different QA teams for the trunk and the new dev branch in place who did not want to talk to each other? Great Scott :-(( – Doc Brown Jan 4 '17 at 17:49
14

At that stage of merge I would say that automated merging may only over complicate the process. I have had similar issues with branches that have diverged for over a year and the most effective method I have is to do the following:

  • Take a copy of the original unmerged state
  • Diff between the unmerged and latest
  • Break down any common elements
    • For example, do all function name changes, then parameter changes, etc.
    • Ignore white space on diff if standards have changed, otherwise you will waste a lot of time counting spaces
  • Focus on the core functionality first

Eventually compiler warnings and the diffs will be your best friends, keep using the unmerged diff to see exactly what was different and just keep going. There might be various tools you could use to help, but that will be up to you to find which is best.

The key is to keep going.

Edit:

A word of warning, this approach will mean that version control history would become 'corrupted', as you'd lose the evidence of the branch-to-branch merge, as well as the unmerged branch's history.

Thanks to comments from 'Jack Aidley' and '17 of 26'

  • 1
    The major problem with this approach is that it will destroy the record of changes left in the version control system. – Jack Aidley Jan 4 '17 at 12:21
  • Essentially by making all of the same changes a second time during the merge, you would still have a log of the changes, it would just be in the order done in the merge instead of the order they were done during development. Not ideal, but better than nothing. Plus you'd still have the original unmerged state, if that was kept in version control. – Erdrik Ironrose Jan 4 '17 at 13:38
  • You would have a log of the changes, but you would not have historical evidence that the changes were merged from branch to branch. This would be a huge deal in TFS, which offers you only the unmerged changesets to choose from when merging from branch to branch. – 17 of 26 Jan 4 '17 at 13:58
  • @17of26 While I agree that you can restore some record of changes, 17 of 26 is correct that this record will not be complete or accurate. It may be that this approach is sufficiently easier as to make this loss of record an acceptable compromise given the bad situation they're now in. However, I think it's an important drawback to recognise regardless of what they decide. – Jack Aidley Jan 4 '17 at 14:17
  • 1
    @Jack Aidley I definitely agree it's quite the problem, so I've added a bit to my answer to reflect. I hope that's alright? – Erdrik Ironrose Jan 4 '17 at 15:06
8

A few years back we had a client with the same requirements of keeping branches separate. So we did.

We never merged their branch back. They had there own unique version. We charged them extra for changes since essentially we had two major trunks instead of 1 main trunk and branches.

We attempted to merge back to trunk but after 2 weeks we decided to abandon that effort as it was burning hours of time with no tangible benefits.

So, don't merge it back. Going forward merge critical fixes to that client branch as needed and any enhancements would be one offs specifically charged to that client.

  • This strategy is only feasible if the different lines of development target different clients. Or, if the use cases where the product is involved allow to to use the two different product lines in parallel, in a non-integrated fashion. To my understanding, the OP describes a situation where the new line of development targets the same client as the one who is using the trunk, and it is unclear if parallel usage of two product lines could make some sense for his case. – Doc Brown Jan 5 '17 at 8:53
1

It is not going to be fun, but how painful it will be depends on the nature of changes, and how isolated they are.

I suggest you attempt to converge the branches through refactoring as much as possible before you do an actual merge.

The merge tool is kind of dumb because it only looks at textual differences and does not understand the code in any way. If the main branch have changed the name of a class used throughout the application, and the feature branch uses the old name in some new code, then the merge tool will not understand that the class name should also be changed in the new code. But if you do a refactoring in branch B to rename the class like in branch A it will work in both old and new code and the merge will go smoothly.

Secondly, you should inspect how localized the changes in the development branch is. If the changes in the feature branch are localized to a few areas, you don't have to converge the unaffected code, you can just copy and overwrite from the main branch.

In areas of code where there have been non-trivial changes on both branches, you have to carefully inspect the code and decide how to rewrite.

protected by gnat Jan 4 '17 at 20:49

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.