Bridging Git and TFS with Git-Tfs

25 August 2012 - Git

Before reading this, I'd recommend reading my previous post, which goes into the core differences between different Version Control System (VCS) features, with a very strong emphasis on Git.

I've used various source control solutions in the past, all with their different pros and cons. Unfortunately, none of my fulltime permanent positions have used Git. I have however used it for a few years for personal and freelance projects, and have fallen in love with it. So much so, that I've opted to use the opensource project Git-Tfs to allow me to use Git locally at work rather than the rather restrictive TFS that is our primary source control system.

What is Git-Tfs?

In the words of its author, "git-tfs is a two-way bridge between TFS and git". This basically means that you can use Git as your source control solution locally, and then push and pull changes to and from a TFS repository. As far as the TFS repository is concerned, it's unaware that the changes are coming from anything other than a standard TFS client. Likewise, the fact that you're using Git locally will not effect your colleagues.

So why use Git-Tfs with TFS anyway?

My current place of work is the first time I've used TFS. First off, I should state that we use TFS 2008, so it's possible that some of my issues have been resolved in later versions. However, the fact that TFS isn't distributed does suggest that a lot of the benefits I enjoy with Git could not be in later versions of TFS anyway.

The first thing that struck me with TFS was when I viewed my pending changes list. All I had was a single list of checked out files. Each file has a tickbox, and there's a textbox at the top to specify your checkin comment. That's it. There's no way to create multiple named pending changelists (like you can in Perforce). You have to (at checkin time) work out which files are part of the particular change you want to checkin, and then go through your list of pending changes ticking them. This results in developers creating huge single checkins with lots of unrelated changes because it's much easier and less time consuming than trying to work out which files belong to which potential checkin. Perforce allows you to have multiple pending changelists which you can assign custom names to. This makes life much easier, but only goes so far given that a specific file has to be in either one pending changelist or another.

With Git, because you have your own local repository, your workflow is quite different. You don't need to create multiple pending changelist because you can just create temporary local commits. Remember that until you push your changes back to the master repository which is used by other people (TFS in this case), you're free to manipulate existing local commits in any way you see fit. This includes combining, splitting, reordering, editing, and deleting commits.

Or alternatively, you can easily create temporary local branches. This is one of the many things that makes Git so powerful. It is so easy to create, delete, and manage branches. In most source control systems, branches are expensive and tend to only get created for major versions and milestones. With Git, you can create branches per feature, easily merge changes from one branch to another, and perform various other ways to manipulate changes across branches. Once you've finished with a branch, you can just combine the commits in this feature branch back to the main branch (via a single rebase command), and then delete it. I quite often find myself creating temporary local feature branches when I'm working on a feature, creating lots of checkpoint commits which I combine and tidy up before merging it back into the main branch ready for pushing to TFS.

Installing Git-Tfs

The easiest way to install Git-Tfs is via the Chocolatey package manager. Chocolatey is like apt-get for Windows and makes installing and updating software a lot simplier. Once you've got Chocolatey installed (which is in itself just a single command line command copied and pasted from the Chocolatey homepage, you can then install Git-Tfs by typing "cinst GitTfs".

Using Git-Tfs

Once installed, you will first need to clone your TFS repository to create a local Git repository. The first time I tried this, I tried to clone into my existing project directory. The problem with this is that it was already mapped to my TFS workspace. As TFS works by making non-checked-out files readonly (the lock model), and Git doesn't use the read/write file attribute (the merge model), this of course causes conflicts. I quickly realised that my Git project needs to be in a separate folder that wasn't mapped to a TFS workspace. Infact, I no longer needed a TFS workspace mapped at all. I'm using Git locally and not TFS after all!

So to clone from TFS, in your command prompt, change to the directory you wish the project to be cloned to (not including the project name's subdirectory), and type:

git tfs clone  

For example:

git tfs clone http://my-tfs-server:8080 $/MyProduct/MySubProject

That's it. You now have a local Git repository with all the change history locally mirrored. You can then make changes and local commits, then push those commit back to TFS with:

git tfs rcheckin

The rcheckin command will take each of your un-pushed commits one at a time and add them to the TFS repository creating TFS changesets.

To get any new changes that team-mates may have checked into TFS, you can use one of the following:

git tfs fetch
git tfs pull

The difference between these two commands is that fetch will just get the new changes, but not merge or rebase it into your local master branch. Pull will get the changes and merge it into your local branch. I personally prefer to fetch and then rebase the changes into my local branch. This makes the history look a lot cleaner and more linear. So I normally do:

git tfs fetch
git rebase tfs/default

Visual Studio Source Control Bindings

Another issue I had was with our Visual Studio project files contained TFS source control binding information. As the rest of the team use TFS, I obviously can't remove the bindings. So each time I loaded a project in Visual Studio, an annoying dialogbox popped up asking if I want to temporarily ignore the bindings or permanently remove them. To get around this, I found a Visual studio plugin called Go Offline. This adds a menu option to the File..Source Control menu allowing you to take a project offline without actually modifying the project files.


Coincidentally enough, whilst writing this post, Microsoft have announced another project called Git-Tf (yes, I know). I haven't tried this yet, but at some point will write a followup post comparing the two. It's Java based, and designed to be cross platform (whereas Git-Tfs is Windows only).


I hope this post proves helpful if you decide to try Git-Tfs. It has certainly immensely improved my source control workflow at work. If you have any thoughts and experiences on either Git-Tfs or the newly released Git-Tf, then I'd love to hear about them.


Recent Posts

Featured Posts

.NET Oxford Links