The tool migrates your code. It doesn't migrate your thinking.
TFVC to Git, planned, converted, and cut over, whether you're landing on Azure Repos or GitHub.
Book a free 30-minute callThe conversion tool exists. Click the button and 180 days of history later you have a Git repo. For a small project with a clean history, that's the whole job. For a $/Main that's been accumulating since TFS 2008, with folder branches nobody remembers making, solutions that reference each other across the tree, a nightly build that only works because of a workspace mapping somebody set up in 2014, and 40 GB of history that's mostly binaries checked in "temporarily," the button converts your mess into a different kind of mess.
And you can't put it off much longer. YAML pipelines require Git, on Azure DevOps and on GitHub. New Azure DevOps organizations can't even create classic pipelines by default anymore. Microsoft's own migration tooling is Git-to-Git only, so there is no path from TFVC to GitHub that doesn't go through this. Nobody will say TFVC is deprecated; the signal is in what they've stopped investing in. You're not choosing whether. You're choosing when, and whether it gets planned.
I've been doing TFS and Azure DevOps work since 2005. Converting TFVC to Git, for teams staying on Azure DevOps and teams leaving for GitHub, is a large part of what I do now. Here's why it's harder than you think.
Sound familiar?
"We tried the converter. It ran for two days and produced a repo nobody could clone."
"There's one $/Main. Everything is in it. Nobody can tell me what's still alive."
"Our branches are $/Main, $/Dev, $/Release-2019, $/Release-2019-hotfix, and about thirty more."
"The build works. Don't ask why. It has something to do with a workspace on the build server."
"Half the team has never used Git. The other half uses it at home and is scared to say so."
"We were told to be on GitHub by next quarter. We're on TFS 2015."
What actually has to be decided
The tooling is the last step. These are the decisions that come before it, and skipping them is how conversions produce a repository nobody can use.
- How many repositories. TFVC has one repo per collection. Git uses the repo as a boundary: a deployment unit, a permissions scope, a CI/CD trigger. Monorepo imports the dysfunction wholesale; solution-based repos are usually right, and one TFVC tree is usually three to twelve of them. Where the seams go is the decision most of the arguing is about, and the one the tooling can't make.
- Whether the solution roots are clean. A solution-based repo only works if everything the solution needs lives under the folder where the
.slnlives. TFVC let that get informal for years. It has to be unambiguous before the conversion, because an ambiguous root in TFVC is a broken build in Git. - Cross-root references. A project in
$/App1/src/referencing a library over in$/SharedLibs/Common/works in TFVC because there's one repo. In Git, that reference points at nothing. Every one of them is a broken build at 4pm on a Thursday. The fix is a package feed, and it has to exist before the conversion, not after. - How much history. The built-in tool brings 180 days. Full history takes different tooling and a decision about whether you want it: twelve years on a tree that's about to be split nine ways is nine repos of mostly irrelevant history each. All of it, some of it, or a clean start with the old tree archived read-only.
- Folder branches.
$/App/Dev,$/App/QA,$/App/Prodare directories, not Git branches, and the tool doesn't turn them into Git branches. Which folder is main, what happens to the rest, and whether the branch-per-environment model should survive at all. It usually shouldn't: short-lived branches, a protected main, branch policies or rulesets, and a release strategy that doesn't need a branch per version. This is where the team's habits get redesigned, not just the tree. - Load-bearing workspace mappings. Solutions that only build with exactly the right folder mappings, cloaks, and remaps on the right machine. Git has no equivalent; you clone the repo, you get the repo. That's not a migration problem, it's a structural problem TFVC was hiding, and the migration is where it becomes visible.
- Binary dependencies. The
$/Lib/folder of DLLs someone checked in back in 2014 goes into Git history forever. Finding them, deciding what becomes a package and what's a Git LFS candidate, and cleaning them out before every clone takes an hour. "We'll move those to a feed later" has a way of becoming never. - The builds. If you're on TFVC, you're on classic pipelines, and every one of them points at TFVC paths that won't exist. Re-pointing them at Git is an afternoon's clicking into a model that isn't getting new features. The real answer is YAML, and it's a rethink rather than a translation: classic kept build and release apart, YAML doesn't, and environments and approvals move to a different place.
- The people. The team that's been on TFVC for a decade needs more than a cheat sheet. They need to know what a pull request is for, why the branch is short-lived, and what to do when the merge goes wrong. That's training, and it's scheduled before cutover, not after.
How I do it
1. The TFVC Conversion Assessment
A fixed-price, two-week, remote diagnostic of your TFVC estate that ends in a written report and a sequenced conversion plan. It's for teams staying on Azure DevOps and converting to Azure Repos Git, and for teams whose only open question is source control.
Week one is spent inside the tree and with the people who know it. Not a questionnaire: I read the collection, map the solution roots, find the cross-root references, inventory the folder branches and the workspace mappings that builds depend on, and talk to the people who made them, if they're still there.
Week two is the write-up, a draft you react to, and a readout. What you get:
- The inventory. Solutions, roots, branches, binaries, and builds, with what's live and what's dead. You'll be surprised by the dead number, and every dead branch and folder is one you don't have to convert.
- The findings. Every cross-root reference, every load-bearing workspace mapping, every binary that shouldn't be in history, stated with its consequence.
- The plan. How many repositories and where the seams go, how much history and how to get it, which branches convert and which get a tag, the package feed that has to exist first, the new branch model, and the build changes, in the order they have to happen.
- A sizing. Enough to budget the conversion with. You can take it to anyone, including your own team.
Fixed price: $10,000, for one Team Project Collection or Azure DevOps organization. That's the same as the GitHub Readiness Assessment, because the TFVC tree is where most of the two weeks go either way. If you then want me to do the conversion, the plan is the scope and the quote comes from it.
If GitHub is the destination, the GitHub Readiness Assessment covers the TFVC tree along with everything else in the estate at the same price, so buy that one instead. If you buy this one first and the answer turns out to be GitHub, it's credited toward the migration engagement.
2. Prepare
The cascade runs in one direction: TFVC to Git, Git to packages, packages to clean repo boundaries, clean boundaries to CI/CD events that mean something, and from there to pipelines that make sense. So the preparation happens in that order, on the live TFVC tree while the team keeps working: stand up the package feed and get the cross-root references onto it, clean out the binaries that shouldn't be in history, tag the dead folder branches, and get the builds ready to point at Git. Almost by accident, you end up with real dependency management, which is an architecture improvement that fell out of a source control decision.
3. Convert and verify
Run the conversion into the new repositories per the plan. Then verify: every live branch is there, the history that was supposed to come came, the builds pass on Git, a clone doesn't take an hour. Do it at least twice, because the first run always finds something the plan missed. TFVC stays read-write until the team signs off on the Git repos, and read-only forever after that, because someone will need to look something up in 2029.
4. Cut over
A date. The team trained before it, not after. The old tree locked, the new repos open, branch policies on, and somebody answering questions for the first two weeks. The training is hands-on and specific to your repos, because "Git for the enterprise" from a slide deck doesn't survive the first bad merge.
What the conversion costs
The assessment is fixed price. The conversion is priced from it, because until the plan exists nobody, including me, knows whether this is a two-week job or a two-month one. Once it does, I'll quote the conversion as fixed-price phases with the cutover date on the paper.
Staying on Azure DevOps, or leaving it?
Both are fine. Azure Repos Git is a good Git host and converting to it changes nothing else about how your team works in Azure DevOps. If the real question is GitHub, the TFVC conversion is one line item in a bigger plan, and that's a different page. If you're not sure which question you're asking, start here.