Merging feature branches for QA with TFS (part 2)

In my previous post, we had a look at the problem : how to merge sibling branches with TFS, minimizing the number of conflicts. Yes, the number of conflicts you’ll get depends on the “technique” you’ll be using :

  • TFS baseless
  • Shelvesets
  • Other tools?

All your base are belong to TFS

But first, let’s answer the real question : what should be the base exactly for our 3-way merge?

Let me recap the scenario:

  • branch dev A from Main
  • Main evolves
  • branch dev B from Main
  • Main evolves
  • Both dev A and dev B have evolved as well
  • As a best practice, we integrate latest Main content into dev A and dev B
  • Now we want to test dev A and dev B with a single test campaign, we want to merge them all together, but leave Main intact
  • branch QA from Main, from the version that as been merge to dev A and dev B

     

    SNAGHTML9efd54_thumb

    The base we need is the latest version of Main that has been merged into dev A and dev B. You must have merged the same version of Main into both branches, of course. The QA branch needs to be branched from the same version of Main as well. These conditions are common practice and should not be a problem.

    Here the base is not the most recent common ancestor, or it depends on what you call an ancestor. It is easy to understand : I want to merge “the diff between latest Main and dev B” into dev A. And dev A evolutions must be compare to the latest Main version that has been merged as well.

    External tools

    It is not possible to choose your base when you merge with TFS – btw, I’d be curious to know which VCS let you choose a custom base when merging.

    So let’s perform our merge “outside of TFS”. Is that bad? In the end, you won’t have any merge history between those branches, but you we really need that? What looks important to me is to keep the dev history on the dev branches for a little while, for reference, and that the QA branch future merge into Main remains easy.

    3-way folder merge procedure

    Use a local Workspace that maps the QA branch. Map also in any workspace dev A, dev B, and the Main branch (the version your merged into dev A and dev B if ever Main has further evolved).

    Merge dev A into QA with a baseless merge (easy when using VS 2012 and TFS 2012 remember last post?). Take the Source version for every conflict (easy merge isn’t it?), you can select all conflicts and choose the option.

    Let’s now use KDiff3, and its wonderful folder 3-way merge feature :

    image_thumb

    KDiff3 is ugly, but the best merge tool I know at the moment. It is just quite clever and has nice features:

    SNAGHTMLface99_thumb

    Note that you will also loose the renames during the process, which will break the history of the renamed files. You can perform the renames in the Source Control Explorer if you like (do this before resolving the merge, and rescan afterwards).

    When finished, the local workspace (new with TFS 2012) is your friend, it will detect what has been changed, added and deleted in the Pending Changes window:

    image_thumb1

    The final tradeoff is :

    • You have less conflicts than when using TFS (even with baseless merge as explained in the previous post)
    • You break the chain of history, partially
      • In my eyes dev history is not very important, I’d be glad to debate on this. I mean not as important as maintenance history!

    If you have a large code base to merge, that should be worth it! Happy merging Smile

  • Merging feature branches for QA with TFS (part 1)

    or How to merge sibling branches with the least conflicts as possible

    In this post series I’ll propose a simple procedure to merge feature branches among them without merging into Main. This is particularly useful when you want to test the features altogether (or by groups of features) without bringing yet all the content onto the Main branch. If you have a large code base, you also want to avoid conflicts as much as possible.

    image_thumb3

    Team Foundation Version Control (TFVC) is a great version control system as long as your respect the branching and merging guide produced by the ALM Rangers. You can handle pretty complex situations and have branching trees such as this:

    image_thumb

    © Visual Studio ALM Rangers

    All is well under control as long as you merge between branches that have parent-child relationship. Should you need to merge between any pair of branches, you can always :

    • Use a TFS “baseless” merge
    • Use a Shelveset (code stored at server side in a separated storage that you merge onto anything)

    TFS baseless merges (really baseless?)

    To achieve a baseless merge you have to type a command like:

    tf merge /baseless $/Project/SourceBranch $/Project/DestBranch /recursive

    More on the merge command here. That will create a merge relationship between two branches with no obvious connection (read parent-child). Now the merge relationship is established, subsequent merges are then managed by TFS UI (Visual Studio) and history engine. Good.

    But still, this king of merge is not very satisfactory because TFS is not very good at picking the most recent common ancestor “in a clever way”. Don’t laugh too fast, Git is not very clever either at picking up the best base.

    Here is the best scenario you can get with TFS when merging sibling branches: the base is the origin of the branch you are merging from. When merging with the command line, you should use the /version parameter to select only wanted changesets, don’t take the changeset that created the branch, or the whole branch will be a conflict. Take only the changesets your are interested in, as explained by Buck Hodges here. In this precise case (schema below), I selected all the changesets but the one that created the branch dev B, in order to merge its contents into dev A.

    SNAGHTML2ce926_thumb

    I’m lying, the UI can do it!

    Ok, sorry, but since this feature is new in TFS 2012, don’t blame me too much if put in my article a bit of TFS history!

    So with TFS 2012, it is now very easy to perform baseless merges in the UI. You can edit manually the target branch in the merge wizard. Then choose to pick the changesets you want:

    image_thumb6

    Then select the changesets you want to merge (without the branch creation):

    image_thumb9

    Made with Brien Keller VS 2012 VM Smile

    Using Shelvesets

    The trick is to use the TFS power tools to unshelve your content to a different branch. The command will “translate” server paths to another location (that you must have mapped in your Workspace):

    tfpt unshelve /migrate /source:$/Project/SourceBranch /target:$/Project/TargetBranch

    They are very handy but don’t expect a top notch merging experience regarding to the conflicts that are generated. Before TFS 2010 SP1 baseless merges improvements, they were kings for moving fixes from branch to branch. Now, that baseless have improved, I’m not so sure, I go “baseless” more and more.

     

    Next post I’ll talk about a solution, there is no magic, we’ll use external tools to achieve our goal. Till then, just think, what base is the best in such a case?

    Stay tuned!