Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@idlem1nd
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save idlem1nd/ad5f55a82c3e76cf2a56 to your computer and use it in GitHub Desktop.
Save idlem1nd/ad5f55a82c3e76cf2a56 to your computer and use it in GitHub Desktop.

Migrating from TFS to Git

This is a quick how-to of my experience using the git-tfs bridge to keep a TFS repository in sync with a Git repository, which subsequently allowed TFS to be migrated away from completely.

The git-tfs tool

At the time of writing, the latest version of git-tfs has issues with TFS branches that have been renamed and/or reparented. It also struggles with baseless merges. We will use pmmiosec's fork of git-tfs, specifically the rename_branch, which resolves issue #480 with git-tfs. Full instructions on building git-tfs from source can be found here, but to summarise:

# Get the source code
git clone --recursive git://github.com/pmiossec/git-tfs.git
cd git-tfs
 
# Update submodules (libgit2sharp)
git submodule update
 
# Switch to rename_branch
git checkout rename_branch

# Build with MSBuild in Release configuration
msbuild GitTfs.sln /p:Configuration=release
 
# Make sure the dependencies (VS2012 SDK) are installed before doing the above.
# You may need to edit the build configuration in the solution file using Visual Studio 
# to remove the projects for SDKs you don't have e.g. GitTfs.Vs2008, GitTfs.Vs2010, GitTfs.Vs2013

#Also make sure MSBuild 4.0 is in your path (included in .NET Framework 4.0)

Cloning a TFS repository with git-tfs

Open a command prompt with local admin priviledges and change to an empty directory where that you want to clone the TFS repository into. Make sure that both git and git-tfs are in your PATH. It also helps to be running as the Windows account that has priviledges to access TFS, as this account will be passed to the Team Foundation Server automatically by git-tfs. Once the clone completes, a local git repository will have been created as a subfolder with the same name as the TFS branch you cloned (i.e. "Trunk" in this case).

# clone the repository with all history, branches and labels (warning, this may take a few hours!)
# we pass the fully qualified URL to the TFS Collection, and then a project/branch path to the Trunk.
git tfs clone http://localhost:8080/tfs/DefaultCollection "$/Project/Trunk" --with-branches --with-labels

Keeping a git-tfs repository in sync

You can keep this repository up to date with changes from TFS by pulling from all the remote branches. This assumes you want to use this repository solely to sync with the remote TFS i.e. you aren't doing any work in the local git repository which you are worried about losing.

# the remote branches will have all been added in git-tfs, to verify:
cd Trunk
git tfs branch
 
> Development -> http://localhost:8080/tfs/DefaultCollection $/Project/Development
>       refs/remotes/tfs/Development - ab9e15392aa985994f4ebf47b48cfc34ab905c43 @ 2219
> default -> http://localhost:8080/tfs/DefaultCollection $/Project/Trunk
>       refs/remotes/tfs/default - 3d3d551544da822f09653a570d0038ea90f86c0f @ 2243
> etc.
 
# to pull all of the ahead commits on all TFS branches into your repository 
git tfs pull --all 

Pushing updates to a remote Git repository

When updates have been pulled down from TFS, they can be pushed back to a Git remote. In this way you can keep your remote Git repository (i.e. a central shared server) up-to-date with all changes in TFS. Again, it is assumed that you aren't using the Git repository for local work, and that others aren't committing changes to the remote Git repository, which could cause merge conflicts. The changes are pushed in exactly the same way as if this was a normal git repository i.e. we revert from using git-tfs back to plain git.

# add the remote (if you cloned using git-tfs, this won't be set up)
git remote add https://example.com/repository.git
 
# verify the listing
git remote -v
> origin  https://example.com/repository.git (fetch)
> origin  https://example.com/repository.git (push)
 
# now push everything, all branches, force
# WARNING! This is only safe if this is a write only server for sync during migration, 
# and others are not pushing work in separately. If not, don't use force and resolve conflicts.
git push --all -f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment