Get yer Git on

By | March 11, 2014

One of the more interesting aspects of moving to VisualStudio Online for my source control and builds when I did it was seeing that I now had the choice between TFS Version Control (TFSVC) and Git to use as my source control. At that time I had never used Git. However, when I saw this while Team Foundation Service was still in beta (before it became I told a buddy of mine. Who worked for Microsoft. And from what he knows, it sounds like MS is on its way to deprecating TFSVC in favor of Git, hence the dual offering.

With this in mind, let’s see how we can also deprecate our source control repos in favor of Git, AND migrate them to!

Before this little operation I housed two separate repos of source code. One on BitBucket using Mercurial as the backing store, and one on VSOnline using TFSVC as the backing store. The reason for the two separate areas is that BitBucket allows unlimited private repos, which I used for my personal WP/Win8 apps, and VSOnline allows better team collaboration (pseudo-public) also for free (up to 5 members) which I use when I have myself and a few buddies working on an app. It also has a more integrated experience w/ VS (of course) to do defect tracking & stuff.

Let’s get this party started, shall we? Dude, I wanna skip to TFVC -> Git!

Mercurial to TFS Git

If you’re curious about the differences between Mercurial and Git, since they’re both effectively DVC (Distributed Version Control) systems, read this.

What you’ll need

Setting up a new TFS Git project

  1. Log in to your VSOnline account
  2. Click ‘New’ under Recent projects & teams
  3. Name your project
  4. If you have a preference on process template, choose accordingly (doesn’t matter for the purposes of this exercise)
  5. Select Git as the Source Control Provider
  6. Click Create project


VSOnline works its magic and you’re shortly presented with


You can choose ‘Close’ here then head over to Visual Studio

Connect to your VSOnline account and choose your newly-created Team Project



Now we clone this (empty) source code repo to our local machine. Remember the location to which you clone the repo as you need it later.



Now we’ve got a Git receptacle for our Mercurial project!

Next, fire up the Git Bash prompt



First step is to clone the git repo of a tool that does the Mercurial –> Git migration for you (WITH HISTORY) by interacting with Mercurial via Python. Hence the need for the toolset above.

git clone git://

this repo will be put in a ‘fast export’ folder at the current location of the git bash prompt (your Home directory, eg: c:\users\brandon)

If you didn’t clone via Visual Studio

next, make a spot to put the git-flavor of your Mercurial repo. You could do this in explorer, or right from this prompt

mkdir myProject-Git
cd myProject-Git

Now you need to initialize this directory as a Git repo

git init

If you did clone via Visual Studio, start here!

Since you created the folder and cloned a repo to it, you only need to change your working directory to that location so the migration script puts stuff in the right place. In my VS example, I cloned to <my user directory>\blogsample-git so I just

cd ~/blogsample-git

Now you’re ready to take your Mercurial repo and transition it to Git. You do this by executing one simple command thanks to the repo we cloned above. For the purposes of the command I’m going to show, assume that my Mercurial repo is at ~/myProject (where ~ is my user directory)

~/fast-export/ –r ~/myProject

What this line does is tells the fast-export script to run on the Mercurial repo at ~/myProject, and create the new git flavor in the current directory (hence why we cd’d to our new git folder earlier).

When this runs, you might get an error. The only one I ever encountered was one saying that there was more than one Head in my Mercurial repo. Every time it said this sure enough somewhere in my history I had branched my repo and not merged it back in to the trunk. So check on this before you get started or you’ll be doing it now. The nice thing is that the error message tells you the exact rev # of the offending change so they’re easy to find in something like HgWorkbench. If this happens just merge that spot back in (resolving conflicts however you want) and re-run the tool per the last line above.

Here’s what the output looks like when I migrate Who Called Me? from its Bitbucket Mercurial repo to my new blogsample-git/ TFS Git local repo:


Once this is complete, head back over to Visual Studio to commit the repo back to your VSOnline account.

Double click the entry for your new team project, notice it no longer has the “download folder” icon next to it because you cloned the repo.


Here’s where I got confused. I clicked ‘Changes’ because I thought I’d need to commit my newly-migrated changelist that came from Mercurial to the local Git repo.


Whoa, what’s with all the deletes! I thought we added all these files from the Mercurial repo?!

Check your local folder where the repo lives


What the…?

Turns out the script we ran migrates the history and everything to the Git metadata. So it basically does the commits associated with each Mercurial checkin. This doesn’t necessarily affect the filesystem. What’s this mean for us? Pretty simple. Git sees it as though we have all this history in our repo, but not files on our drive. So it’s marked the pending change as “delete” for every file that’s missing. So just undo our “changes”!


Click “Yes” on the “Are you sure?” prompt and have a look at your filesystem now


Sweet! Let’s verify we have full history. Click ‘Unsynced Commits’ in the Changes area of Visual Studio you’re currently staring at:



Boom! This is showing we have all these local commits (changesets) that haven’t been pushed back to our TFS Git repo. How do we do that? Click the ‘Push’ button!

And you’re done!

Of course, if you’re a Git command-line monkey you can do all the same steps I outlined here with the command line options. As a newbie to Git I’m not quite there yet. ;)

Now on to the next option


What if you have projects in VSOnline that are currently using TFSVC as the source control repo and you want to move those to Git, too?

Here’s where the “rumor” that MS is transitioning TFSVC to Git really gets some legs. Microsoft’s released just such a package to make this possible. For the purposes of what we’re doing here, though, I’m going to use git-tfs, an OSS 2-way sync between the two, “similar to git-svn”. Even better yet, it’s a super-cake install.

What you’ll need

First, install git-tfs using the oh-so-difficult Chocolatey install command:

cinst gittfs

Follow the same steps above to create a new Git-based Team Project. Git-tfs will create a local Git repo based on the Team Project name, so you don’t have to worry about creating a new folder anywhere.

Once you’ve done that, in a command prompt change to the parent folder of where you want the repo to live and utilize the git-tfs awesomeness:

mkdir gitRepos
cd gitRepos
git tfs clone https:// account><collection name> $/<project name>

and you’re off to the races! Here’s output from me doing this for my Blogs project source code:


I honestly don’t know what that warning is about or what exactly it means, but things work fine without it. Here we see the changeset numbers coming over as Git hashes. Now let’s have a look at the repo in VS. Keep in mind we have not cloned an existing Team Project to the location that Git-TFS just put stuff, so this flow is a little bit different.

In VS, Add a “Local Git Repo”:


Double-click the resulting repo entry in the Team Explorer


The import difference with Git-TFS is that, unlike Mercurial, when it migrated our TFSVC to Git, it actually copied the files as well. This means in Explorer you’ll see:


So, we won’t see any “pending changes” in Team Explorer. Instead if we want to verify history, we have to have a gander at the history of our branch. Every Git repo has a ‘master’ branch and since this repo was just created, and branches aren’t part of cloning TFS –> Git, our current state is labeled as ‘master’. We get to history in VS like this:



And voila! Full history!


Now to wire this up to a TFS project so we can push these changes to the remote repo. As you saw when we looked at the branches, ‘master’ is listed as an Unpublished branch. We need to change this.

From the Branches view, click ‘Unsynced Commits’


You’ll notice the distinct absence of the “Push” ability that we had when we went the Mercurial route. The reason for this is that when we cloned from TFS –> local in the Mercurial migration, part of that clone is to store the remote repo information so VS already knew about it. We have to manually punch that in for this scenario.

VSOnline provides the information we need here by providing the command-line calls you need to make if you were to do this without an IDE. In your VSOnline account, select your Git-based project and go to the Code area


Right there you’re presenting with a notification that your repo is empty, along with instructions on how you can Push an existing repository to the location. That’s exactly what we have here so let’s take a look at the instructions:


Taking this information and punching it in to Visual Studio gets us where we want to be (and avoids that caveat of enabling basic authentication ;) ):


Upon clicking ‘Publish’ the push is done and you’re set! The local repo has been pushed to your VSOnline account!

I hope you found this useful. If you have, don’t forget to share it!