Mar 28, 2011

How To: In Place Branch Switching with TFS 2010

One of the nice features of some of the newer version control systems is the ability to do fast in-place branch switching.

This is really useful when you are working on a web application and you have mapped an IIS virtual directory to your source folder and want to switch between branches without having to reconfigure your IIS mappings.

If you’re using TFS then most likely branch switching is a pain because you have branches mapped to separate folders and have to constantly close the solution, remap IIS and open the solution again from the other branch folder.  But you don’t have to! You can actually have multiple branches using the same local working folder, just not at the same time.

Here’s how to do in place branch switching with TFS 2010.

Starting Point

Let’s assume we have the following source tree in TFS, with a branch per story arrangement (this is using Source Control Explorer in Visual Studio 2010).  We currently have no branches mapped, thus the grey folders.

image

Let’s now map the integration branch and then get the source locally to our working folder.

image

image

When we look at the workspace details we then see this:

image

Switching Branches In Place

Now let’s say I want to switch to one of my story branches to make some changes.  The easiest way is right click the folder in source control and select “Map to Local Folder”

image

Alternatively, if you have the power tools installed into VS2010, you could click on the path mapping at the top of the source control explorer window:

image

We then enter the same working folder that we used for the integration branch above.  Given we’re wanting to reuse our working folder this should be obvious.

image

image

If we now look at source control explorer we’ll see that the integration branch is no longer mapped (it’s greyed out) and that our 2703 story is now the active branch.

image

We can confirm this by looking at the workspace details, seeing that the integration branch is no longer mapped and that our story branch is set to the working folder.

image

Note that if you change the source control folder in the working folders section of the workspace dialog you will also trigger the remapping operation.

When the get operation executes to pull down files, TFS will only send you files that are different between the two branches. It’s not a full recursive get, which means this operation is quite fast.

Note that this only works if we are switching between TFS branches.  If you try switching between non-branch folders you’ll get an error indicating the folder is already mapped.

image

Command Line Goodness

OK, so let’s go and switch back to the integration branch but this time we’ll do it via the command line.  We need two commands for this:

tf workfold /map <<< to change the workspace folder mapping

tf get /remap <<< to bring the local folder contents up to date

image

And as you can see TFS 2010 has only given us the files that are different between the branches.  Nice.

Now, you may ask, why would I use this method and not do it all via Visual Studio 2010?

Well, firstly it’s faster to do it this way (at least for me it is), plus it’s very easy to create a small batch file to make this even quicker and simpler, but a more pragmatic reason is that if I have a solution open when branch switching occurs then you’ll see this in Visual Studio 2010:

image

Which means I have to wait for the solution to close, for the get operation to complete and then I have to manually reopen the solution.  It’s easier than closing the solution in one folder and reopening the solution from another folder, but it’s still somewhat annoying.

If on the other hand I do the branch remapping from the command line then I simply get this:

image

Visual Studio just prompts to reload open files that have changed, which makes the switching process much easier since I only can just click yes to all and be done.  Note that if project or solution files have changed you’ll be prompted to reload them, but there’s no simple way around this.

Oh, one other reason for the command line usage is that at times Visual Studio gets confused about the workspace mapping changes and can sometimes block the switch by showing the “already mapped” error we saw earlier.  The command line has no such problems that I’ve seen.

Hang On! What If We Have Pending Changes?

Fair enough.  Let’s see what happens.

Assume we’re currently on the integration branch and that we have edited a file.  The pending changes window shows this pending edit.

image

If we now switch to the story branch we get a conflict:

image

So at this point we do the obvious and click “Checkout File and AutoMerge”, right?  Well, not so fast!

image

This is because the file hasn’t been downloaded to our workspace yet (remember we’re switching our workspace around). Here’s what we see in source control explorer if we want proof:

image

I’d much rather the pending changes window didn’t show the unusable option, but that aside, we grudgingly take the only choice available to us and overwrite the local file.  Our changes are wiped out and the file is now exactly as it is in the story branch we just switched to.

At this point if we look at the pending changes window we see this…

image

Huh? What’s up with that? TFS is saying there’s a pending change on our file that we just overwrote, but this is the pending change for our original branch isn’t it?  If we check in at this point would we make a mess in our original branch.  Urgh!

What if we now didn’t look and we went and edited EngineTest.cs in our story branch?  If we do and we refresh the pending changes window we see this:

image

Ah! So the refresh of pending changes shows that we not only have a change in our current story branch but that we also have a pending change for the integration branch still hanging around, but that the integration branch change isn’t mapped to a local file.

I should probably check that integration change in so things don’t get confusing.  If we switch back to the integration branch, what happens?  Why, we get a merge conflict of course!

image

Well, we’d better overwrite the local file since we it currently contains changes for the story branch not our integration branch

Unfortunately if we do so, our local changes will now be gone.  The pending changes we had floating about somewhere are toast!  In fact if we try and commit a file that is not currently mapped we get a dialog like this:

image

Hmm. OK. Not great.

Good Practices for In Place Branch Switching with TFS 2010

This means that in order for us to make branch switching as painless as possible with TFS, we should remember a few simple things:

  1. Ensure there are no pending changes before switching.  Use shelvesets as needed to preserve changes.
  2. The command line is faster.  Don’t be afraid to use it.
  3. Ensure our workspace mappings are to folders marked as branches in TFS 2010

And that’s it.  Go make the most of it, and if you bump into any edge cases feel free to post a comment about it.

4 comments:

  1. And this should make it obvious to anyone why GIT has become so popular... There are so many corner cases where working with GIT is trivial and TFS is a pain.
    This is one such example. Branching from a changed workspace. Working with multiple branches. GIT just feels right.

    ReplyDelete
  2. I was the poster of the previous post, but wanted to add one little thing.

    Thanks for the great article, it was really helpful to me!

    ReplyDelete
  3. I use this technique all the time and it has sped up my development process. However, tf get /remap fails frequently and reports "no changes." So, it needs to be run multiple times to pick up on changes that needs to be re-applied. I have not yet determined if this is a defect with tf get or something else.

    ReplyDelete
  4. This doesn't work no matter what I try, in TFS 2012. If I try to do the steps in the GUI it just won't work

    ReplyDelete