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.
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.
Let’s now map the integration branch and then get the source locally to our working folder.
When we look at the workspace details we then see this:
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”
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:
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.
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.
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.
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.
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
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:
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:
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.
If we now switch to the story branch we get a conflict:
So at this point we do the obvious and click “Checkout File and AutoMerge”, right? Well, not so fast!
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:
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…
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:
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!
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:
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:
- Ensure there are no pending changes before switching. Use shelvesets as needed to preserve changes.
- The command line is faster. Don’t be afraid to use it.
- 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.