February 2010


I created a tool called git-tfs. I alluded to it the other day. I’ve been using it for about a month on a solo project, and a few other people are picking it up.

As of a few days ago, I released its source code. (I plan to move the ‘official’ mainline to my company’s fork, eventually.) As of today, there’s a pre-built binary that I’ve called v0.9.

To install, you first need git (e.g. msysgit). Download git-tfs and add the extracted directory to your path (or somewhere else that git can find it).

To use, you need to clone your TFS repository. Then you use git like normal, and occasionally fetch of shelve to synchronize with TFS. I’m pretty comfortable with fetching from TFS. I plan to add more ways to push data into TFS.

For cloning: git tfs clone http://tfs:8080 $/MyProject/MyDir my_git_clone

Clone is the same as init + fetch. git-tfs’s clone and init are happy to add itself to an existing git repository or to create a new one for you.

To shelve: git tfs shelve “Shelveset name”

I opted for shelving first for a few reasons. First of all, it’s pretty safe: there are no permanent changes made to the TFS repository. Also, it sidesteps a couple of tricky issues, including: work item association and source control policy validation on the TFS side; and history preservation vs. rewriting on the git side. I would like to have a way to replicate git commits back into TFS, but that’s not done yet.

First, a disclaimer: some of the things I describe in this post involve directly changing data in TFS’s databases. This isn’t usually recommended. Also, I was using TFS 2005. I’m not sure how much of this works on other versions.

A couple of weeks ago, while a coworker and I were deploying some new work item types, we created a field as an Integer that we realized needed to be a String. Changing the field’s type in the work item type definition results in the error “TF26038: Field type for My.Custom.Field does not match the existing type. It was Integer, but now is String.”

A quick look on google made it look like there wasn’t a good way to change the field type. I tried updating the Fields table in the database. This looked like it worked, but the actual fields on the work item type didn’t get updated, so we couldn’t only insert integer data. Non-integers failed with a strange error; for me, it said that the TFS server was offline. So the quick-fix in the database was obviously a bad fix.

So now the question was, how do we preserve the existing data in a new field?

Step 1 was to create a new field. The first attempt used the same friendly name, but a different RefName. Team Foundation objected: “Error: Field name ‘Custom Field’ is used by the field ‘My.Custom.Field’, so it cannot be used by the field ‘My.Custom.Field2’. So now, I’m thinking about trying to change the type of the column in the database. Theoretically, SQL Server can do this. If I’d had some planned downtime, I would probably have gone this route. I wasn’t sure that changing the database column type would be the last time I had a problem, so I wanted to use TF’s tools to do most of the work.

Also, around this time, I (re)discovered the witfields tool.

Here’s what I did.

  1. Created a new field, My.Custom.Field.Temp, as a String, and added it to the work item type with witimport.
  2. Looked in the Fields database table for the FldId of the old and new fields. For example, the old field had FldId 10138 and the new one was 10146.
  3. In each of WorkItemsAre, WorkItemsWere, and WorkItemsLatest, I copied everything from Fld10138 to Fld10146.
  4. I used witimport to remove the old My.Custom.Field field from the work item type.
  5. I used witfields to delete the old field from the database.
  6. I updated the work item type with a new field, My.Custom.Field.
  7. I repeated steps 2 and 3 to get the data from the new field to the fixed old field.
  8. I used witimport to remove the temp field from the work item.
  9. I used witfields to remove the temp field from the database.

It looks like this worked, and each step was pretty quick, and I wasn’t too worried about being interrupted between steps. That said, I make no claim that this will work for you. If you decide to try this, definitely read up on the TFS commands you’re using, and quadruple-check the SQL updates you run.