Lately, I have seen the below remarks coming through in the communities:
I’ll be using the TFS API to show you how the “Get Latest” is supposed to work and show you how you can avoid getting in a situation where you might have to use “Get Specific” to get the latest version of your workspace. I would assume that you know the basics of TFS workspace, if not, please refer to this blog post from Martin WoodWard on the introduction to TFS workspaces.
1. Get Local Workspace Information Programmatically using TFS API
As you start working with the source code, you are prompted to create a workspace mapping. Conceptually, I like to think of a TFS workspace as a container that bridges the gap between your local computer (acting as a TFS client) and the server. TFS is able to map the folders on the servers against your local and smartly store the last changeset id associated with that file in your local workspace cache.
Let’s write some code to try this out, I will be using the Workstation class that represents a machine and the source control state on it. Two important things to note here:
LastSavedCheckin
– The last saved check in id is stored in the cache in your local workspace. ServerGuid
– This is the unique server GUID to validate the server version of the file.
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection
(new Uri("https://tfs2010:8080/defaultcollection"));
var service = tfs.GetService<VersionControlServer>();
var localWorkspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(
@"C:\Src\Temp_UK_1\Development\Prod\Source\TfsWorkspaceManager\
TfsWorkspaceManager\TfsWorkspaceManager\TfsRepository.cs");
Debug.Write(String.Format("Identifier in Local Workspace =
{0}", localWorkspaceInfo.ServerGuid));
2. What Actually Happens When You Get Latest?
I am using the TFS API to get the latest of the TfsRepository.cs file below:
var getLatestOfTfsRepositoryCs = service.GetWorkspace(
@"C:\Src\Temp_UK_1\Development\Prod\Source\TfsWorkspaceManager\
TfsWorkspaceManager\TfsWorkspaceManager\TfsRepository.cs");
So using a .NET decompiler, we can see that the GetWorkspace
method internally calls the GetLocalWorkspace
method which internally calls the GetWorkspace
method performing 2 key steps, which is validating that the file GUID matches the GUID of the server and that the downloaded changeset
id is cached.
Example: Let’s Discuss What We Saw Above With Several Scenarios
Scenario 1
You trigger a Get Latest Version and get all the files from the server, one of the files is TfsRepository.cs and its version on the server is 42.
You check out the TfsRepository.cs, open it and add another method to it.
You save the file but you don’t check in the file.
You trigger the Get Latest Version once again.
A check is being made in the workstation cache and the source control finds that the server has version 42 for TfsRepository.cs and on the last Get Latest Version, you got 42, so nothing happens to this file.
You check your local changes and you can still see them.
Scenario 2
You trigger a Get Latest Version and get all the files from the server, one of the files is TfsRepository.cs and its version on the server is 41.
You check out the TfsRepository.cs, open it and add another method to it.
You save the file but you don’t check in the file.
You trigger the Get Latest Version once again.
A check is being made in the workstation cache and the source control finds that the server has version 42 for TfsRepository.cs and on the last Get Latest Version, you got 41.
The source control also sees that your local version contains changes, so it triggers the merge tool.
3. When Does Get Latest Fail?
If I clear the workstation cache, TFS will lose the workstation information and fail get latest. Let’s try this out:
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection
(new Uri("https://tfs2010:8080/defaultcollection"));
var service = tfs.GetService<VersionControlServer>();
Workstation.Current.RemoveCachedWorkspaceInfo(service.GetTeamProject
("TEMP_UK_1").VersionControlServer, service.AuthorizedUser);
var localWorkspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(
@"C:\Src\Temp_UK_1\Development\Prod\Source\TfsWorkspaceManager\
TfsWorkspaceManager\TfsWorkspaceManager\TfsRepository.cs");
Debug.Write(String.Format("Identifier in Local Workspace = {0}",
localWorkspaceInfo.ServerGuid));
var getLatestOfTfsRepositoryCs = service.GetWorkspace(
@"C:\Src\Temp_UK_1\Development\Prod\Source\TfsWorkspaceManager\
TfsWorkspaceManager\TfsWorkspaceManager\TfsRepository.cs");
Example: Let’s Discuss What We Saw Above With Several Scenarios
Scenario 1
You trigger a Get Latest Version and get all the files from the server, one of the files is TfsRepository.cs and its version on the server is 42.
You go in to the workspace, right click properties and remove the read only flag.
You add several new methods to the file.
You trigger the Get Latest Version once again.
A check is being made in the workstation cache and the source control finds that the server has version 42 for TfsRepository.cs and on the last Get Latest Version, you got version 42 so nothing happens to the file.
Scenario 2
You trigger a Get Latest Version and get all the files from the server, one of the files is TfsRepository.cs and its version on the server is 42.
You delete the file.
You don’t check in the deletion.
You trigger the Get Latest Version once again.
A check is being made in the workstation cache and the source control finds that the server has 42 for TfsRepository.cs and on the last Get Latest Version, you got 42, so nothing happens to this file.
You check your local file system and you find that the file is missing.
If you un-mark a file as read/write, edit it and then do a "Get Latest" on that file, then it will not be replaced with the latest version from the server (because you never told the server (by checking out the file) you were messing with that file so it assumes it you didn't). In that scenario, you would want to use the "Get Specific..." option to force a get of the file.
So now, next time when that new Analyst you hired in the team comes over to you and complains that TFS Get Latest is not working, you know who to blame. ;)