Migrating from TFVC to GitHub

June 17, 2020

Migrating from TFVC to GitHub

So, why should you move your source code from TFVC (Team Foundation Version Control) to GitHub?

In this article I will describe how you can move your source code from TFVC to GitHub. You probably wonder why I don’t recommend Git in Azure DevOps (Azure Repos), and the reasons are two:

  1. The secure code parts are much more advanced in GitHub than in Azure Repos
  2. The integration with Azure DevOps is really good. You can still use Azure Boards and get commits and pull request history in your work items, and you can also use Azure Pipelines to build and deploy your applications when your code is in GitHub.

Here are my reasons for instead using GitHub:

1, Pull Requests

Pull Requests in GitHub are comparable with Code Reviews in TFVC, but even better. They provide:

Code review with

  • Traceability
  • Build integration
  • Quality.

A way to make sure changes that go into main code line are mature, of high quality and safe.

2, Local operations and local branching

Everybody has fully featured version control locally, can do everything locally and then decide what gets pushed to remote into their feature branches.

3, Branching

Git is perfect for feature driven development using feature / topic branches.

4, More people know how to work with Git than TFVC

It’s a world-wide standard supported by lots of tools and platforms.

5, The same build definition can build from any branch

Git switches branches in place, compared to TFVC in which you have to map different paths on disk. Additionally, Git always looks at a specific commit point in time, so it’s easy to switch between.

6 , New development of the TFVC platform?

TFVC will still be there for a long time, but not much new functionality is released.

So how do we migrate?

If possible, select just one branch to migrate. That will make your migration much easier and it could also be a good time to evaluate your branching strategies.

Tip migration

The easiest and the way I recommend doing it is by doing a tip migration, that is, you leave history behind and only migrate the latest version.

This is the way to do it:

First, create a Git repo in GitHub. Make sure you add a .gitignore file that matches your development tool, and readme file as good measure. A gitignore file specifies intentionally untracked files that Git should ignore, like dlls.

Next, run the Git Clone command to get a local copy of your nearly empty repository to your disk:

Git clone https://github.com/yourorg/yourrepo.git

  • Get the selected branch from TFVC to disk (get latest from for example Visual Studio)
  • Git works best without binaries, so you should remove them and other unwanted files. It’s quite common for older projects to have their NuGet packages checked in with the code. This is a great opportunity to replace them with feeds to NuGet.org.
  • Copy your files from the TFVC folder to the cloned Git folder
  • Add your files to Git tracking control, commit them and push all to your remote

git add * git commit -m "Added new files" git push origin master

Move with history

But what about history, what if we need that?

In this case I recommend that you download and install this tool: https://github.com/git-tfs/git-tfs

Next, run the git tfs clone command. In the sample I will only migrate master, but you can migrate all branches even though I don’t recommend it.

git tfs clone http://tfs:8080/tfs/DefaultCollection $/project/master

Add a .gitignore, https://gitignore.io and commit it to the repo:

git add * git commit -m "Added gitignore"

Next step is cleanup. gitignore prevents us from adding new dlls and other files to the repo, but we want to remove old dlls, pdbs and other files that might be there. For that we use git filter-repo that you can find here: https://github.com/newren/git-filter-repo. If you don’t have Python installed on your machine you have to install that as well.

First, we analyze repository history and create a report that we use to determine what to delete:

git filter-repo –analyze

Looking into paths-all-sizes.txt we can se that we have both dll’s and nupkg files that should be removed in the package folder:

To remove the package folder and everything in it with this command. You could add several –-path commands in a row if you want.

git filter-repo --path "packages" --invert-paths

After cleaning it looks like this, much better. Next step could be to remove the NuGet.exe.

Connect your local repo to your remote:

git remote add origin https://github.com/yourorg/yourrepo.git

Push your code to your remote and we are ready:

Git push --all origin

Other tools

There is also a built-in way to migrate from TFVC to Git in Azure DevOps, but I don’t recommend it as it does not let you clean up your code on the way. I think it’s OK to use it if you are sure that there are no unwanted files in your repositories history.

How about other artifacts?

At the moment, you can’t migrate policies, pull request and other artifacts unless you use the Azure DevOps and GitHub APIs. However, tools for this specific scenario is under development and we’ll post about this on our blog as soon as we see the news.

Solidify and GitHub

Earlier this year, we announced the exciting news that we became one of the world's first GitHub Advanced Services and Technology Partners. It's a tool we very much enjoy, and understand why so many others do, too. If you're interested, take a look at our GitHub page here. If you want to know more about us here at Solidify, take a look at our About page.