TFS Source Control for Config Part I: Why Branching Doesn’t Work

 Comments Off on TFS Source Control for Config Part I: Why Branching Doesn’t Work
Jan 292012

Part I: Why Branching Doesn’t Work
Part II: Labelling, Branching’s Poor Cousin
Part III: Apps Without Source Integration

Most of the information out there on TFS Source Control is in the realm of software development, concerning the intricacies of branching, merging, build automation and all that good stuff.

But what if you want to use TFS to version configuration files? By that I mean the many artifacts that don’t get get compiled into an application but control how it behaves – I’m thinking of report definitions, data mappings, calculation logic and the like. As a broad definition, I call “configuration files” any sort of soft-coded business rules or settings. Configuration files might be edited in Visual Studio but also plain text editors, custom-built apps, or a vast range of third-party applications. XML is a typical format, but config files can be any plain text or binary structure (although the latter is thankfully less common). Often, the files are generated and modified by non-programmers: analysts, business people, subject-matter experts, and specialists in the particular technology being used.

Configuration files are no less critical than the application itself; in fact they can be much more valuable – representing many man-years of effort analysing complex business logic into a machine-friendly format. Such important assets need the rigour of version control, but how should that be set up? A good branching strategy is the right place to start for application code, but branching is not great for incremental releases – which are commonplace for config changes. Here’s why:

  • Granularity: merging works at the changeset level and gets ugly if you attempt it at a finer level. Even though it’s possible, I also try to avoid merging specific changesets and instead merge only whole branches – otherwise it can get difficult to track what’s going on. Bill Heys has a great post on why you should avoid Cherry Pick Merges.
  • Versioning: branching works for application code because it ensures integration and testing of a consistent whole. For config, you often need to identify individual files or small subsets which will be released independently. Branching doesn’t help there.
  • Conflicts: there’s no branching without merging and that means the possibility of conflicts. Traditional line-based code lends itself nicely to standard merge tools but XML, proprietary text formats and (especially) binary don’t fare so well.

If branching is out for versioning config files, what approach should be taken instead? I’ve seen organisations manage the problem by recording changeset numbers or copying files to shares. Neither are particularly satisfactory, not least because of error-prone recording and the heinous crime of duplication. In the next part of this short series I’ll look at labelling as an approach.

Jan 222012

TFS 2010 has two “container” levels to separate instances of source control, work items and build: Project Collections and Team Projects.

I think “Project Collection” and “Team Project” are both quite confusing terms, bordering on misleading. If you jump right into TFS without spending time on the books, blogs and ALM Rangers material you would naturally set up one Team Project for each of your, well, projects, and maybe use Project Collections to group together handfuls of related projects. My advice: that’s the last thing you should do.

Instead of taking the names at face value, look at them like this:

Project Collection = Organisation

Project Collections cannot see each other at all. They are a way of having complete separation without needing multiple installations of TFS (as you did prior to the 2010 version). Each Project Collection has its own SQL Server database and there are very few reasons to have more than one, namely:

  • Portability: You can quite easily detach a Project Collection and move it to a different TFS instance
  • Performance: If SQL Server starts creaking you can split Project Collections for performance reasons (but explore all other performance improvements first)
  • Law: If there is some regulatory reason why your data must be kept completely separate, multiple Project Collections will do that for you (caveat: the reporting database is shared between project collections).

If in doubt, remember: you can split a Project Collection with no loss of data but you can’t join them together again. (OK, you can use the TFS Integration Platform to migrate them together but you lose fidelity, as it “replays” the source and work item history into the new database, and there are elements that can’t be migrated at all).

Summary: Unless you have a very good reason not to, have one Project Collection per organisation.

Team Project = Team

Team Projects live together in a Project Collection, and can see each other transparently. However, each Team Project has entirely its own configuration in security, source control and work items. If you have a team that works on different projects, with team members moving regularly between projects or even working concurrently on multiple projects, the administrative burden of having a separate Team Project for every “real” project is likely to make your head spin.

Team Projects are good for separating teams or processes, which are hopefully the same thing – you don’t want one team following more than one process, do you? Sure, if you have a large project with a distinct team and it’s own way of working then a new Team Project is what you need – everything can be configured and customised just how that project needs. Otherwise, go with the “Project of Projects” approach outlined expertly by Martin Hinshelwood.

Summary: Have one Team Project per team, not per project.

 Tagged with:

Capturing “Done” in VS/TFS 2010

 Comments Off on Capturing “Done” in VS/TFS 2010
Jan 152012

An agreed and fixed definition of “Done” (DoD) for an iteration is a powerful thing. It sets a quality bar that applies to all the team and all the work, avoiding wasteful discussions. At the retrospective the definition can be reviewed and the bar raised to push the quality up a notch, or if the team is failing to meet the definition actions can be agreed to remedy the situation.

To be effective, the team needs to find a way to verify each piece of work against the DoD. To keep the process lean, it helps to build verification into the process in as simple a way as possible. There are different ways of setting this up in TFS, for example work items could be customised to include fields for each part of the DoD, and those fields could become mandatory when setting the status to Closed. However, this approach requires the team member who closes a work item to vouch for all the work that went into it – work that may have been done by several people over days or weeks.

Instead of using work items directly, I believe the best way to track the DoD is at two “gates”: check-in and build. Check-ins should be small and frequent, and with continuous integration builds run on every check-in, so this gets the tracking of “done” as close as possible to the execution of individual pieces of work (i.e. tasks). This way, check-in policies and the build provide automatic checking, while check-in notes can be used to verify elements of the DoD which cannot be automated. Here’s an example DoD and how it can be tracked using those mechanisms:

Example Definition of “Done”

  1. Code builds
  2. Code has been reviewed
  3. Code is covered by unit tests
  4. Code changes can be traced to requirements
  5. Unit tests pass

Check-in Policies

These are a great tool to maintain check-in standards. As previously posted, check-in policies can be overridden but it’s easy to set up an alert to detect that. The TFS Power Tools are a must-have here as they provide a number of check-in policies including the crucial Custom Path Policy – which scopes other policies to specific folders. I find the following policies very useful:

  • Changeset Comments Policy: requires a comment for every check-in. These should be used to provide a high-level summary of what has changed rather than why (why is captured better with a work item link).
  • Work Items: requires a work item to be selected on check-in. This enables traceability to requirements. The policy can be scoped to a specific set of work items using the Work Item Query Policy but I have found this to be over-engineering.
  • Forbidden Patterns Policy: prohibits certain files being checked-in. Best used with the Custom Path Policy and a consistent source structure so the prohibition can be scoped to certain folders. For example, you may prohibit compiled DLLs being checked into source code folders.

Other policies such as Builds, Code Analysis and Testing Policy are in my opinion too restrictive or awkward to use, or are intended to meet requirements that are better met by automated builds.

Check-in Notes

These are simple text fields that can be customised, and made mandatory, for each team project. For example, a code (or peer) review can be verified by making the Code Reviewer field mandatory. This applies to all files in source control, so the team would need to decide if it’s OK to enter “n/a” for non-code check-ins or if all check-ins should be reviewed (including dependencies, documentation etc.) Shelvesets can be used to defer check-in and allow a team member to pick up a potential changeset for review.


The TFS build system offers the greatest potential for customisation. Out of the box it will verify that code builds, and (if you use MSTest for unit tests) run the tests and calculate code coverage. There is an option in the default template to fail the build if any tests fail, but to take it further you need to customise the work flow. This could be used to fail the build if code coverage has dropped since the previous build, or bring virtually any other metric into the mix – enabling you to extend the build process as needed to match an extended DoD.

A really powerful option related to Build is Gated Check-in. This reverses the normal sequence so that build happens before check-in and if the build fails the check-in is rejected. This ensures that not only is the DoD tracked, but that code that does not meet it can never reach the code base and impede other work.