In my previous post I described a VCS branching plan that will remove the need to initiate code freezes. A few of my friends pointed out that their teams do not use that or similar methodologies not because they were unaware of such simple possibilities, but because performing reverse integrations (or any kind of merge) is so difficult with TFS (their ALM tool of choice), that most developers do everything they can (e.g. initiate code freezes) to avoid having to perform a lengthy and painful merge.
My advice is twofold. First, methodology-wise: Merge often! The more often you merge, the smaller and simpler the merge will be. As a rule of thumb, and assuming you are using the simple branching plan I suggested last week, you will want to merge every time you fix a bug (remember – you only merge when doing a reverse integration from a release branch to the main branch). For more complex plans, that have the actual development done on a separate branch from Main, requiring forward integration merges (i.e. from “Main” to “Dev”), you will want to merge on a daily basis, or whenever you know that there’s something to merge (from a release branch or a different development branch).
My second advice, to which I will dedicate the rest of this post, is to replace the diff / merge tool!
It is a well known fact, to those who know it well, that Microsoft have outfitted TFS with a less-than-adequate diff/merge tool, especially when compared to those available to users of SVN, Git, and Mercurial (to name a few).
How so? The primary issue I have with TFS’ default diff tool, is that it shows me which lines are conflicting, but it’s up to me to find out just how they differ from each other.
This is how the default tool shows the difference:
Found the difference? Difficult, isn’t it? The default diff-tool provided with TFS marks the lines that are different; it doesn’t show you what the actual change is.
Here’s what it looks like in KDiff3:
See the difference now? The actual changes are marked, not just the line. Makes comparing the code with the other version much simpler. By the way, in case you are visually impaired, what I did was replace the word “TFS” with “custom”.
The second, and more important part of the tool, is the actual merging capabilities. I’ve got a major gripe with the default tool as well. TFS’ merge tool performs a 2-way merge, where as other tools (KDiff3, for one) performs a 3-way merge.
What’s the difference you ask? Basically, a 2-way merge compares two files and attempts to best-guess what the differences between them are – this is rather error-prone, and thus requires more human intervention. 2-Way merges are good enough for simple merges, like those done every time you commit (or check in) changes to your code base. When you are trying to resolve a conflict between your changes, and the changes somebody else made, you just might be in for what is (dis)affectionately known as merge-hell. This happens when two developers made changes to the same source file, especially when the changes are located close to each other (i.e. same or consecutive lines of code).
3-way merges, on the other hand, compare both versions of the file to their parent version, and therefore can focus on comparing the changes made, rather than the complete files. This allows for a more reliable automatic merge, which means that the merge will be much simpler. Even if an automatic change is not possible, the tool’s focus on the actual changes helps the developer decide whether to include one or both changes.
Okay, I’m Convinced! Give Me the Goods!
Good! Luckily, it is very easy to replace the Diff/Merge tool in TFS. This is done on the client side, from within visual studio.
Following is a step-by-step guide for how to do replace the merge tool. I know that most of you don’t need this level of detail, but for those beginning developers or those of you whose brains have been terminally damaged by long hours of merge-hell, here it is:
Open the Tools | Options menu.
This will bring up the Visual Studio configuration window.
Now select the Source Control > Visual Studio Team Foundation Server menu. At the bottom, press the Configure User Tools… button.
This will open the (surprisingly named) Configure User Tools window
Press on the Add… button to add diff and merge custom tools. Doing so will open the following window (so many windows; I hope you aren’t confused):
Filling in the information is rather simple; You add the file extensions for which you wish the tool to be used (comma separated, prefixed with a period like “.cs”). You then select the operation you wish to associate with the tool. Note that for diff/merge tools there are two commands you wish to use – Compare and Merge. Remember to do both.
Next you select the command – that’s the actual tool you are going to use. KDiff3 is a great tool, both free and powerful (not to mention popular with the Git and Mercurial crowd. If they like it must be cool), and is my tool of choice. Other popular choices include Beyond Compare (version 3 and up only, as prior versions do not support 3-way merges, and you really want that for your reverse-integration merges), DiffMerge, and TortoiseMerge (especially if you were dragged away from SVN kicking and screaming).
Finally you enter the command arguments. If you are daunted (as I often am) by having to find out what arguments you need, then fear not! I found this great post from a few years back, that lists a whole bunch of tools with the command-line arguments you need in order to use for TFS.
For KDiff3, use the following argument values:
Selecting a better diff/merge tool will greatly improve your merging experience, and hopefully alleviate most of your pain when performing those reverse integrations. Remember to merge as often as you can, so that each merge will be small and painless.
If anybody has any other ideas, experiences on how to make using TFS’ version control system easier, please share!
It never ceases to amaze me, that to this day, I come across so many development teams that still initiate code freezes every time they release software. In this post I will show you why this is wasteful and how the need can be avoided altogether!
Code Freezing is the act of temporarily stopping all new development while focusing all of the resources on maintenance of the latest release. While releasing the latest feature set is usually the highest priority, it is often the case that the development team must divide their efforts between fixing the latest version (V-latest) and developing the next version (V-next).
Development teams and managers initiate code freezes because they cannot find a good, simple way to handle both development efforts at the same time.
Code freezes waste valuable time and resources. Each code freeze means that developers working on new features must either delay checking-in their code (until the freeze is lifted), or avoid working on the features altogether. Adding up the amount of time each developer is not working, or spending on complex check-ins & merges is the total amount of time wasted for each code freeze!
Fortunately, with most modern version control systems (TFS, SVN, etc.), it is possible to solve this problem, with a proper branching plan!
The following branching plan is just the core plan, which may be refactored to allow for multiple development and testing configurations, as well as more complex release mechanisms (e.g. releases, service packs, hot-fixes, etc.):
The plan consists of (at least) the following branches:
Main – On this branch the latest features are developed and tested. Your nightly build or cutting-edge version is built from this branch.
Release / Version – Whenever it is time to release a version, or before beginning to work on a feature for the next version, a new branch is made from Main. A release branch is made for each release version.
Working with the Basic Plan
The development team develops new features on the Main branch.
When it is time to release a version (to QA, end of sprint, etc.), and before developing features for the next release / sprint, make a Release branch (branch off main).
From this point on, the team keeps developing new features only on Main.
The team fixes issues with the latest release, only on the Release branch.
Important fixes from the version branch are reverse-integrated (RI) – i.e. merged back – into Main.
This process is repeated for each new version to be released.
Simple, isn’t it? I showed a friend of mine a draft of this post, and he asked “Isn’t this trivial? Why are you talking about this?”. I had to agree. It is trivial. But too few teams do this. I personally think that most teams simply do what they always did, because that’s how their managers did it when they were developers, a long, long time ago…
If you keep this up (dare I say religiously?) you will never have to freeze your code again; new features will never affect older versions. Developers can maintain old versions and develop new ones at the same time.
I think that once you try this, you will agree that this is a simple easy win.
If you want to learn more about branching plans for version control systems, a group called the VSTS Rangers (catchy, eh?) put together a great guide for branching with TFS. This guide can be easily applied to any VCS.
As for freezing yogurt, Please make mine with strawberries. It tastes great.