tf get /version:T /recursive

Remove binaries and build tools

Due to the way Git stores the history of changed files by providing a copy of every file in history to every developer, checking in binary files directly to the repository will cause it to grow quickly and cause performance issues.

For build tools and dependencies like libraries, adopt a packaging solution with versioning support, such as NuGet. Many open source tools and libraries will already be available on the NuGet Gallery, but for proprietary dependencies, create new NuGet packages.

Once dependencies are moved into NuGet, make sure that they will not be included in the Git repository by adding them to .gitignore.

Convert version control-specific configuration

Team Foundation Version Control provides a .tfignore file that will ensure that certain files are not added to the TFVC repository. This can be used for automatically generated files like build output so that it is not accidentally checked in.

If the project relies on this behavior, convert the .tfignore file to a .gitignore file.

Cross-platform TFVC clients also provide support for a .tpattributes file that controls how files are placed on the local disk or checked in to the repository. If a .tpattributes file is in use, convert it to a .gitattributes file.

Check in to TFVC and perform the migration

Check in any changes that remove binaries, migrate to package management, or convert version control-specific configuration. Once this final change is made in TFVC, the import can be performed.

Follow the Import repositories documentation to actually perform the input.

Advanced migrations

The Git-TFS tool is a two-way bridge between Team Foundation Version Control and Git, and can be used to perform a migration. Git-TFS is appropriate to attempt a migration with full history, more than the 180 days that the Import tool supports, or to attempt a migration that includes multiple branches and merge relationships.

Before attempting a migration with Git-TFS, be aware that there are fundamental differences between the way TFVC and Git store history:

  • Git stores history as a snapshot of the repository in time, while TFVC records the discrete operations that occurred on a file. Change types in TFVC like rename, undelete and rollback cannot be expressed in Git. Instead of seeing that file A was renamed to file B, it will only track that file A was deleted and file B was added in the same commit.
  • Git does not have a direct analog of a TFVC label. Labels can contain any number of files at any specific version and can reflect files at different versions. Although conceptually similar, Git tags point to a snapshot of the whole repository at a point in time. If the project relies on TFVC labels to know what was delivered, Git tags may not provide this information.
  • Merges in TFVC occur at the file level, not at the entire repository. Only a subset of changed files may be merged from one branch to another. Remaining changed files may then be merged in a subsequent changeset. In Git, a merge affects the entire repository, and both sets of individual changes cannot be seen as a merge.

Because of these differences, it is recommended that users do a tip migration and keep their TFVC repository online, but read-only, in order to view history.

To attempt an advanced migration with Git-TFS, see cloning a single branch with history or cloning all branches with merge history.

Update the workflow

Moving from a centralized version control system to Git is more than just migrating code. The team needs training to understand how Git is different from the existing version control system and how these differences affect day-to-day work.

Learn more about migrating from centralized version control to Git.