How to determine the latest changeset in your workspace


[UPDATE 7/25/14] Added equivalent API calls.

When you run get for your entire workspace without any argument, you are requesting that the server give you the latest set of files.  Later you might wonder what changeset was used in that get.  To figure that out, you can use the following history command from the root (top) of your workspace.

tf history . /r /noprompt /stopafter:1 /version:W

Here’s what that command means.  The “. /r” part says to look at the current directory recursively, which is why you must run it from the root (top directory) of your workspace.  Here I’ve specified “/noprompt” so that I don’t get dialog, but that’s optional.  The “/stopafter:1” option tells tf to print only one changeset.

The version option is the part that tells the history command to consider history only up to what you have in your workspace.  The “W” means workspace, and without the workspace name and owner being specified it means the current workspace.  The version option could also be written as “/version:1~W” to explicitly state that you are interested in history only up to what is in your workspace.  The “1~” is implicit when it is not specified.  Changeset 1 is when the root of the repository ($/) was created.

Since the history command sorts the changesets from highest to lowest, the result is that the command displays the highest changeset version of all files currently in your workspace.

Here’s the code to do the equivalent using the Version Control client API.

 // The workspace info for the provided path
 WorkspaceInfo wsInfo = Workstation.Current.GetLocalWorkspaceInfo(filePath);

 // Get the TeamProjectCollection and VersionControl server associated with the
 // WorkspaceInfo
 TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(wsInfo.ServerUri);
 VersionControlServer vcServer = tpc.GetService<VersionControlServer>();

 // Now get the actual Workspace OM object
 Workspace ws = vcServer.GetWorkspace(wsInfo);

 // We are interested in the current version of the workspace
 VersionSpec versionSpec = new WorkspaceVersionSpec(ws);

 QueryHistoryParameters historyParams = new QueryHistoryParameters(filePath, RecursionType.Full);
 historyParams.ItemVersion = versionSpec;
 historyParams.VersionEnd = versionSpec;
 historyParams.MaxResults = 1;

 Changeset changeset = vcServer.QueryHistory(historyParams).FirstOrDefault();

Comments (12)

  1. RadioTFS – Remotely TFS Visual Studio Magazine on Inside VSTS: Security in Team Foundation Server, part

  2. Perfect! Just what I needed. Thanks!

  3. Mark Matten says:

    Well, what if you've done "get latest version" on a specific file only?

    You're workspace isn't at the version, just one file is.

    How can one tell this?

  4. Miriam M says:

    tf info (or tf properties) also yields a Workspace version, but it is a dfferent number than the number that comes out of the command above. Why the difference? Which one is the 'real' workspace version?

  5. buckh says:

    Mark, if you've done get latest on only one file and in general want to support your workspace not being a given changeset, then you are in a more complex situation where trying to determine the latest changeset doesn't equate to anything meaningful.

  6. buckh says:

    Miriam, the answer takes you into what's actually recorded. The post was about how to find what is the point in time (changeset) that your workspace equates to if you run tf get with no arguments, which means get your whole workspace up to latest. The equivalent explicit sequence for "tf get" would instead be "tf changeset /latest /noprompt" and then "tf get /version:C123" where 123 would be replaced with what tf changeset /latest showed.

    What you are seeing with tf info if you run it on a set of files is the version of each individual file. Here's an example.

    Local information:

     Local path : c:sunshineSunshineMSBuildCopyapp.config

     Server path: $/Sunshine/MSBuildCopy/app.config

     Changeset  : 23

     Change     : none

     Type       : file

    Server information:

     Server path  : $/Sunshine/MSBuildCopy/app.config

     Changeset    : 23

     Deletion ID  : 0

     Lock         : none

     Lock owner   :

     Last modified: Saturday, January 21, 2012 3:47:32 PM

     Type         : file

     File type    : Windows-1252

     Size         : 144

    Local information:

     Local path : c:sunshineSunshineMSBuildCopyb.cs

     Server path: $/Sunshine/MSBuildCopy/b.cs

     Changeset  : 91

     Change     : none

     Type       : file

    Server information:

     Server path  : $/Sunshine/MSBuildCopy/b.cs

     Changeset    : 91

     Deletion ID  : 0

     Lock         : none

     Lock owner   :

     Last modified: Tuesday, February 28, 2012 6:17:33 PM

     Type         : file

     File type    : utf-8

     Size         : 3162

    That's output from an old project. That workspace is at latest. The changeset listed for app.config is 23, and the changeset for b.cs is 91. Since the local changeset matches the server changeset, I know I have latest for these two files.

    The latest changeset for a given file is the last changeset in which it has been changed. The file app.config was last changed in changeset 23. It's still at latest because there is no newer version.

    Hopefully that helps.

  7. Miriam M says:

    Your examples are for specific files, while I want to understand the situation on he root (top) of my workspace.

    Suppose I run the command from your blog plost at my top location:

    C:WebApp123WebApp123 Team ProjectDevsNext> tf history . /r /noprompt /stopafter:1 /version:W

    This yields:

    12092

    Then I run:

    C:WebApp123WebApp123 Team ProjectDevsNext> tf info .

    This yields CS 12046 for both local and server version; this is a lower changeset than the one from the history command above.

    I interpret this now as follows:

    The lower CS from the info command is the CS in which the _directory_ _itself_ was changed for the last time; there might be changes somewhere down in the directory tree where, for example, a file has been changed in a higher changeset than 12046, but always lower than or equal to 12092.

    The higher CS from the history command (with /version:W option) is the CS in which one of the files or folders from the directory tree has been changed; it is the latest changeset where any change has occurred in my workspace (looking from the root).

    For both commands: the CS that I get back depends on the location where I run the command. Somewhere lower in the directory tree, the numbers might be different.

  8. buckh says:

    Miriam you are correct. Each item has its own version number that reflects when it was last changed. The most extreme example is that tf info $/ will yield changeset 1 since it gets checked in during installation.

  9. David Gardiner says:

    What would be the equivalent API call(s)?

  10. Sam C says:

    Yes, I'm also trying to work out what the API call equivalent is?

  11. buckh says:

    Sam and David, I have added the equivalent code to do this.