Building a Specific Version with Team Build

Team Build by default gets the latest version of your sources (or tip) from source control.  For the most part, this is probably the behavior you would want and expect.  But not always - you might want to reproduce a particular build that got deleted, for example; or you might want to build your latest changest without including changes other users might have checked in.

Unfortunately, getting (and therefore building) a specific version from source control is not supported out of the box in Team Build version 1...  The Get task used in Team Build (this can be found in Microsoft.TeamFoundation.Build.targets) looks like this:

 <Target Name="CoreGet"
 Condition=" '$(IsDesktopBuild)' != 'true' "
 DependsOnTargets="$(CoreGetDependsOn)" >

 <!-- Get all the latest sources from the given workspace-->   
    <Get Condition=" '$(SkipGet)' != 'true' " 
       Workspace="$(WorkspaceName)" 
       Recursive="$(RecursiveGet)" 
        Force="$(ForceGet)" />
     
</Target>

The Get task also a Version property that is not used here.  It defaults to "T" , or the tip version.  To get and build a specific version from source control, you will need to set this property. 

There are several options here:

  1. You can override the CoreGet target in TfsBuild.proj.
  2. You can modify the CoreGet target in Microsoft.TeamFoundation.Build.targets directly.
  3. You can set the SkipGet property to true and override BeforeGet or AfterGet instead.

Modifying Microsoft.TeamFoundation.Build.targets is not a good idea - this would need to be done on every build machine, could get wiped out during an upgrade or installation repair, etc.  Overriding CoreGet is usually not recommended either, since the CoreXX targets will almost certainly be changing in the next release of Team Build.  In this case, however, overriding CoreGet (option 1) is essentially indistinguishable from setting SkipGet and overriding BeforeGet / AfterGet (option 3) and is simpler. 

So - to override CoreGet in TfsBuild.proj, you will want to do something like the following:

 <Target Name="CoreGet"
   Condition=" '$(IsDesktopBuild)'!='true' "
   DependsOnTargets="$(CoreGetDependsOn)" >

   <!-- Get all the latest sources from the given workspace-->
   <Get Condition=" '$(SkipGet)'!='true' "
      Workspace="$(WorkspaceName)"
        Recursive="$(RecursiveGet)"
     Force="$(ForceGet)"
     Version="$(VersionToGet)" />
   
</Target>

At this point, you just need to set the VersionToGet property to whatever version you would like to get.  This can be done in all the normal MSBuild ways - via the command line (put a string in your TfsBuild.rsp file similar to /p:VersionToGet=<VersionSpec> ), declaratively in a PropertyGroup element, programmatically with a CreateProperty task, or via an environment variable.

To reproduce a particular build, you will typically want to set VersionToGet to a label-based version spec similar to "L<build number>" (unless you have modified your build process to use some other labeling scheme).  For example, if you build number is "MyBuild_20060919.1" you could do something like this:

 <PropertyGroup>
  <VersionToGet>LMyBuild_20060919.1</VersionToGet>
</PropertyGroup>