Doing an Incremental Get in Team Build

In Team Build v1.0, it is not possible, without some trickeration, to do an incremental get without also doing an incremental build.  (The process for doing both is documented here, and consits of setting the SkipClean property to true, the SkipInitializeWorkspace property to true, and the ForceGet property to false) 

The short answer for why this is the case is that the CoreClean target wipes out the entire source code directory in order to delete the intermediate binaries...  Here is a condensed version of the CoreClean target from Microsoft.TeamFoundation.Build.targets:

 <Target Name="CoreClean" Condition=" '$(SkipClean)'!='true' ">

 <!-- Call MSBuild /t:Clean for desktop build -->
  <MSBuild Projects="@(SolutionToBuild)" Condition="'$(IsDesktopBuild)'=='true'" Targets="Clean" />

 <!-- Clean SolutionRoot only for end to end build -->
 <RemoveDir Condition="Exists('$(SolutionRoot)') and '$(IsDesktopBuild)'!='true'" Directories="$(SolutionRoot)" />

 <RemoveDir Condition="Exists('$(BinariesRoot)') and '$(IsDesktopBuild)'!='true'" Directories="$(BinariesRoot)" />

 <RemoveDir Condition="Exists('$(TestResultsRoot)') and '$(IsDesktopBuild)'!='true'" Directories="$(TestResultsRoot)" />

</Target>

Because the $(SolutionRoot) directory is deleted for non-desktop builds (i.e. "regular" Team Build builds), setting just SkipInitializeWorkspace and ForceGet to their appropriate values has no effect - the source files are all deleted in any case and must be retrieved again.  Note, however, that in desktop builds the Clean target of each solution in the SolutionToBuild item group is invoked - this should delete the compilation outputs without also deleting the sources, which is exactly what we would need to do to enable an incremental get without also having to do an incremental build

One possibility, then, is to do something like the following:

 <Target Name="BeforeClean">

 <!-- Delete BinariesRoot and TestResultsRoot to be thorough. -->
  <RemoveDir Condition="Exists('$(BinariesRoot)')" Directories="$(BinariesRoot)" />
 <RemoveDir Condition="Exists('$(TestResultsRoot)')" Directories="$(TestResultsRoot)" />

   <!-- Rather than delete SolutionRoot, set IsDesktopBuild to true for the duration of the CoreClean target. -->
    <CreateProperty Value="true">
     <Output TaskParameter="Value" PropertyName="IsDesktopBuild" />
    </CreateProperty>

</Target>

<Target Name="AfterClean">

  <CreateProperty Value="false">
        <Output TaskParameter="Value" PropertyName="IsDesktopBuild" />
    </CreateProperty>

</Target>

NOTE: Thanks to Peter McEvoy for pointing out a bug in this hack - see this forum thread for details.  To work around the issue detailed in the thread, add the following PropertyGroup in your TfsBuild.proj file below the Import of Microsoft.TeamFoundation.Build.targets:

   <PropertyGroup>
    <EndToEndIterationDependsOn>
      BeforeEndToEndIteration;
      BuildNumberOverrideTarget;
      InitializeEndToEndIteration;
      InitializeBuild;
      PreBuild;
      Clean;
      TeamBuild;
      DropBuild;
      AfterEndToEndIteration;
    </EndToEndIterationDependsOn>
    <TeamBuildDependsOn>
      Compile;
      PostBuild;
      Test;
      PackageBinaries;
    </TeamBuildDependsOn>
  </PropertyGroup>

Adding (all) this markup to your TfsBuild.proj file and setting just SkipInitializeWorkspace and ForceGet should get you an incremental get while still preserving a full build.  Note that we are striving to make this process much easier in the next version of Team Build!