Advanced tf.exe syntax, or what on earth is a QualifiedItem?

An item that’s qualified, duh :)  Real answer: it comes from tf.exe versionspec syntax.  Let’s demonstrate by example:

1) tf get foo.cs  # not qualified – falls back to default
2) tf get foo.cs /version:1234  # not qualified – falls back to /version parameter
3) tf get foo.cs;1234  # qualified
4) tf get foo.cs;X56  # qualified with deletion ID
5) tf get foo.cs;X56;LmyLabel  # qualified with both – betcha didn’t know this was possible
6) tf get foo.cs;1234 bar.cs;X56 baz.cs;789 *quux* /version:LmyLabel  # mix & match
7) tf history foo.cs;1234~5678  # qualified with two versions
8) tf history foo.cs;~5678  # default versionFrom, qualified versionTo
9) tf history foo.cs;5678  # same as above
10) tf history foo.cs;1234~  # qualified versionFrom, default versionTo

“Qualifying” an item means telling tf.exe exactly what version to operate on.  We do this by combining a name with a versionspec.  Most tf commands take qualified items as their main piece of input.  (Commands that don’t include things like Checkin, Shelve, Undo, or Status that need to use whatever’s already in the workspace; and of course ones like Workfold or Configure that don’t touch the repository at all).


If you examine tf.exe in Reflector, you’ll see that QualifiedItem is a simple class encapsulating a Path, a DeletionId, and a VersionSpec[] array.  The array almost always has just one member; only a few commands take two versionspecs, and none takes more.  Most items have a deletion ID of 0 to indicate “not deleted.”


To see how it’s used, start by drilling into the VersionControlCommand class to find the methods named ParseQualifiedItem().  I’ll leave this journey as an exercise for the reader.  Suffice to say here’s what you’d find:

Behavior - single versionspec

The goal is to give the user fine-grained control over tf operations.  Examples #1-4 are straightforward.  #5 is a quirk of syntax with no real import.  #6 shows the power of this approach: a single command pulls different versions of foo, bar, baz, while applying a fallback versionspec to all non-qualified items – in this case, the set intersection of all files in the current directory matching the *quux* pattern with the contents of the “myLabel” label.

If not specified by a /version parameter, the default versionspec is T.

Behavior – version range (2 versionspecs)

Example #7 is straightforward.  #8-10 show off some syntax sugar.  When you have a command that expects a version range, you need only type one end of the range if the default suffices for the other.  The default versionFrom spec is C1 and the default versionTo is T.

Note that there is no opportunity for fallback.  You can use the /version parameter or qualified items, but not both.  All of the commands that operate on a version range have additional limitations that make the general syntax seen in #6 impossible.

  • Diff – takes exactly one item with a version range (foo.cs;10~20), or two items with one versionspec each (foo.cs;10 bar.cs;20), but no other variations.
  • History – takes exactly one item with a version range.
  • Merge – takes exactly two items.  The first one has a version range and the second has no version.
  • Rollback – introduces some new parameters that are beyond the scope of this post, not to mention still subject to change before TFS 2010’s release.

One Response to “Advanced tf.exe syntax, or what on earth is a QualifiedItem?”

  1. BUGBUG: poor title » Blog Archive » Birth of a power tool: QualifiedItem and the Powershell pipeline Says:

    [...] that a QualifiedItem represents a simple tuple of {path, deletionID, versionspec}.  By qualifying individual items [...]

Leave a Reply