Everything you ever wanted to know about locks

In TFS a lock is a kind of pending change, in the same category as add, edit, delete, rename, merge, etc. A pending change of type "lock" is not committable, however. You will never look at the history for $/Proj/file.cs and find that in changeset 5678 user A committed a change of type "lock, edit". When using the command line tool tf.exe to work with TFS, locks are sometimes denoted by the ! symbol in textual output.

D:\Workspace1\Proj\main>tf lock /lock:checkout file.txt
file.txt

D:\Workspace1\Proj\main>tf status
File name Change Local path
--------- ------ ----------------------------------------------------------
$/Proj/main
file.txt ! lock D:\workspace1\Proj\main\file.txt
1 change(s)

Checkout locks

There are two types of locks in TFS -- checkout and checkin. The type of lock is selected with the /lock: option to the tf lock command (see above).

If in some workspace, user A has a checkout lock on $/Proj/file.cs, then user B cannot in his workspace place any kind of pending change on the item $/Proj/file.cs. Any attempt to pend a change on the item will result in an error.

D:\Workspace2\Proj\main>tf edit file.txt
The item $/Proj/main/file.txt is locked for check-out by DOMAIN\user1 in workspace Workspace1;DOMAIN\user1.

Checkin locks

If the lock is a checkin lock instead, then user B can pend a change, but is warned that user A has the item locked for checkin.

D:\Workspace2\Proj\main>tf edit file.txt
file.txt

$/Proj/main/file.txt:
opened for lock in Workspace1;DOMAIN\user1

The pending change cannot be checked in until the lock is released by the other user.

D:\Workspace2\Proj\main>tf checkin /i
Checking in edit: file.txt

The item $/Proj/main/file.txt is locked for check-in by DOMAIN\user1 in workspace Workspace1;DOMAIN\user1.
No files checked in.

Lock evaluation and recursive locking

Lock evaluation in TFS follows two important rules. We call this the "upside-down Y" check internally.

  1. When you lock an item, you lock all of its parent folders, up to the root. (This is the top part of the Y.)
  2. When you lock a folder, you lock all of its children, recursively. (This is the bottom part of the Y.)

Here are a few simple consequences of these rules.

  1. If user A has a lock on $/Proj/main/file.txt, then user B cannot rename or delete $/Proj/main. (By rule #1.)
  2. If user A has a lock on $/Proj, then user B cannot create an item named $/Proj/silly.txt, or edit an existing item $/Proj/main/file.txt. (By rule #2.)

The recursive nature of locks on folders can sometimes result in missteps if you don’t understand how TFS evaluates locks. For example, the tf lock command supports a /recursive option. If your goal is to lock the folder $/Proj/main recursively, it is only necessary to lock $/Proj/main -- for example, tf lock /lock:checkin $/Proj/main. The lock will apply recursively downward.

If you instead execute tf lock /r /lock:checkin $/Proj/main, then a lock will be applied to every item under $/Proj/main, recursively. This is not necessary, results in many pending changes, and will significantly slow down lock evaluation by the server.

The /r option for the tf lock command is really only for pattern matching. For example if I wanted to lock all files with extension .bmp under $/Proj/main, I might say tf lock /r /lock:checkin $/Proj/main/*.bmp to accomplish this task.

Automatic locking based on file extension

TFS supports automatic lock behavior based on the file extension being checked out. Any time a pending change is made to an item, the file types list is checked to see if the extension requires automatic locking at checkout. The idea behind automatic locking is that some file types (images, for example) are hard to merge, and that it may be beneficial to keep two people from working on the same item at the same time.

The lock acquired is a checkout lock, as described in the section "Checkout locks" above. A lock that is acquired automatically because of its file extension cannot be undone.

D:\Workspace2\Proj\main>tf lock /lock:none file.bmp
TF10152: The item $/Proj/main/file.bmp must remain locked because its file type prevents multiple check-outs.

The list of file extensions is configurable through the Team Explorer by right-clicking the root (server) node and selecting Team Foundation Server Settings → Source Control File Types.

clip_image002

clip_image004

To disable automatic locking by file type, you can find the file extension you're interested in, click Edit... and check the box for "Enable file merging and multiple checkout."

clip_image006

To disable automatic locking by file type entirely, you can check the box for each type. There are about 12 sets of extensions for which multiple checkout is disabled by default, so it shouldn't take too long.

Automatic locking based on Team Project

TFS also supports automatic lock acquisition (no multiple checkout) at the Team Project level. Right-click the Team Project node in the Team Explorer, and select Team Project Settings → Source Control.

clip_image008

clip_image010

Unchecking the checkbox for “Enable multiple check-out” forces lock acquisition any time a pending change is created under the team project path (in this case, any path under $/Superman). Like automatic file extension locks, automatic locks that are a result of disabling multiple check-out at the team project level cannot be undone.

Unlocking an item

Unlocking can be done in the Source Control Explorer or Solution Explorer by right-clicking the item and selecting "Unlock." From the command line, there is no tf unlock command -- the correct syntax is tf lock /lock:none. Keep in mind that a lock from automatic locking (either by Team Project or by file extension) cannot be undone.

If another user is holding a lock to an item, and has gone on vacation or otherwise cannot give up their lock, a user with the UndoOther permission on the item in question can remove the lock by specifying the item to unlock and the workspace in which the lock exists. By default, members of the [Team Project Name]\Project Administrators group have UndoOther permission at the path $/Team Project Name and below. Here’s an example, where DOMAIN\user2 has $/Proj/main/file.txt checked out for “lock, edit.”

D:\Workspace1\Proj\main>tf edit file.txt
The item $/Proj/main/file.txt is locked for check-out by DOMAIN\user2 in workspace Workspace2;DOMAIN\user2.

D:\Workspace1\Proj\main>tf lock /lock:none /workspace:Workspace2;DOMAIN\user2 $/Proj/main/file.txt
D:\Workspace1\Proj\main:
file.txt

D:\Workspace1\Proj\main>tf edit file.txt
file.txt

$/Proj/main/file.txt:
opened for edit in Workspace2;DOMAIN\user2

You’ll notice that the edit change of DOMAIN\user2 was preserved. Only the lock was removed.

Locks and shelvesets

A lock cannot exist in a shelveset, so if you lock an item and try to shelve it, your lock will be stripped as part of the shelve operation.

However, automatic locks can cause trouble when unshelving pending changes, if you preserve the changes in your workspace when shelving them:

clip_image012

In this case, any attempt to unshelve the shelveset will fail, since you still have the locks in your current workspace. For this reason, we do not use any automatic locking internally.