Finding the changes between two labels in TFS version control

Carl Daniel (code) and Robert Downey (code) each wrote and posted code to show the changesets between two labels in TFS version control.  They each took the same basic approach: call QueryLabels() to get the set of items in each label, find the highest changeset version for each set of items, and then call QueryHistory() with the range of versions specified as the two highest changeset versions found.

There's one technical flaw with this approach.  A label in Team Foundation Server is not a point in time.  In TFS labels are collections of files, each at a particular version.  Brian Harry wrote about this difference in a post titled, Why TFS labels aren't like SourceSafe labels.

In Team Foundation, labels are more powerful.  Instead of being a single point in time, they are able to have versions of each file in the label from different points in time.  The canonical scenario is that you label a build and then find some bugs and want to go back change the versions of a few of the files (either omitting changes that introduced bugs or adding changes that fixed bugs).  Now the label does not represent a point in time, but rather a collection of points in time.  This makes it very hard to display it in a list mixed with change sets because there is not “correct” ordering of the list.  As a result we treat the list of changesets and the list of labels separately.

Another very common approach is creating a label using the versions of files in a workspace.  A workspace is also a collection of files, each potentially from a different point in time.  Team Build labels the files in its workspace as part of the build process.  By doing this Team Build guarantees that it is labeling what it's building.  Steve St. Jean talks about this in his post, Why I Like Labels in TFS Version Control.

By finding the highest changeset in each label to compute the differences, the label is inherently being represented at a point time, as a changeset is just a precise point in time with respect to the state of the repository.  As a result, the report produced by these apps won't necessarily be completely accurate if the label has been changed, such as Brian describes in his example, or the label was based on the versions in a workspace where not all versions are from the same point in time.

Computing the actual set of changes between two labels, taking into account that labels are not points in time, becomes a much more expensive computation involving computing the history of each item between the two changesets in the label (and handling adds and deletes).  In fact, the GenCheckinNotesUpdateWorkItems task in Team Build takes this fully accurate approach, and it's why that task is so slow (see GenCheckinNotesUpdateWorkItems task is expensive and Measuring Performance of Team Build Build Process).  By the way, you can set SkipPostBuild to true in your TfsBuild.proj (add this line: <SkipPostBuild>true</SkipPostBuild>) file to prevent that task from running if you find it too expensive and don't need the changesets and work items recorded in the build information and the "fixed in field" updated in those same work items.

So, should you go with the fast approach used by Carl and Robert or take the slow approach used by Team Build?  The answer depends on whether your labels are points in time and what level of accuracy you need when determining what's changed between two labels.  The approach used by Carl and Robert is completely accurate if your labels are strictly points.  If you need complete accuracy and your labels are not points in time, you'll need the more expensive approach.  If you don't need complete accuracy, the fast approach may give an answer that's "close enough" for what you are doing.

Comments (5)

  1. The Visual Studio Team System User Education blog on New Team Build Customization Content on MSDN.

  2. Mickey Gousset just published on the Team System Rocks blog a new VSTS Links Compilation. Lots of good…

  3. Hey

       I have a requirement in our project, we have our custom msbuild which sends the list of work items list fixed in the current build through mail. The workItems are selected based on the value of the FixedIn field value which is typically the current Build No. Now if the build fails then we have to manually update the Fixed In fields of All the workItem so that in the next build once again the workitem list is generated,as it only picks the workitems Fixed In the current build version..

  4. buckh says:

    Murli, I’m not sure how to explain what you are seeing.  Here is how it is supposed to work.

    Currently the Fixed In field will get updated by each build until the first successful build.  That is, if there are four failed builds before a successful one, the work item will be updated five times.  


  5. If users are using TFS 2010 or above then I think is a good tool.

    TFS ChangeLog applicatoin allows users to automatically generate release notes from TFS. Users will have to provide information on thier project, branch and changeset range and then TFS ChangeLog application will extract information from each changeset in a given range and all the associated workitems to such changesets. i.e. it will travel from starting changeset upto ending changeset and will extract data about each changeset along with associated workitems in an XML file.

    Users can then use their own transformation logic including filter, sorting, styling, output formatting, etc. to generate Release Notes Report.

    TFS ChangeLog application support command line interface as well so that users can generate Release Notes based on windows schedule task.

    Hope this is useful.

Skip to main content