The Great Azure DevOps Migration – Part 4: Validation

wagons migrating west

We have the staging server setup. We’ve cleaned out the data that we don’t want to import. We’re almost ready!

We need to run the Azure DevOps Service validation on our local server to verify that there are no issues before importing. This validation will alert us to any issues that need to be resolved before the actual import.

If you missed the earlier posts, start here.

I highly recommend Microsoft’s Azure DevOps Service Migration Guide.

Get the Tool

Start by downloading the Data Migration Tool. This tool contains the Guide, which you should definitely read, and the actual Migration tool.

Copy the .zip for the Data Migration Tool to the staging server and unzip it to the C:.

Run Validation

Open a command prompt and change directory to the unzipped DataMigrationTool folder. This folder contains the Migrator.exe file.

To execute the validation, run Migrator validate /collection:[COLLECTION_NAME] from the command prompt. Make sure you are executing this on your staging server, use localhost:8080 to make sure you are pointed at the right server.

The validation only takes a few minutes to run and it creates a number of log files with the results.

Analyze the Results

You can view the results of the validation in the command prompt or in the log file stored in the Logs folder of the DataMigrationTool. Open Logs, select the Collection you validated, then click the latest folder (one is made for each migration validation), then open DataMigrationTool.log.

I had a few issues that needed to be resolved, which I’ll explain below. You’ll probably get different ones which you can lookup in the Migration Troubleshooting Guide. None of the issues I ran into were especially hard, just had to read up on the fix.

VS403443 Error

This validation error means that you need to rename a work item field. This seems to happen with old databases that have been updated over time. The schema needs to be tweaked to get in sync with the service.

I had about 8 of these to fix, which I was able to do with the witadmin tool inside the Developer Command Prompt.

witadmin changefield /collection:[COLLECTION_NAME] /n:System.IterationId /name:”Iteration Id”

The important thing (which I screwed up at first) was that the /n parameter is the field, and /name is the name that you change it to.

ISVError:100014 Error

This error means that one of the built-in groups is missing required permissions. It needs to be re-added using the TFSSecurity.exe tool.

Use the instructions at Migration Troubleshooting to resolve this issue.


You may get some validation issues about users, but in my test run I fixed my users after the import by making sure the correct users have access and removing users that didn’t belong.

You won’t get charged till the 1st of the following month after import, so you will have time to address any user import issues.


If you get a warning that your import is too large and needs to be done by importing to an Azure SQL Database first, your import is about to get a lot harder. I initially had this warning, and it is the reason that I cleaned out more of the data in my import (in our previous step). If you can get under this limit, it will make your life easier. If you can’t, you’ll need to do a few extra steps on the import which I won’t be doing, but I’ll provide a link to the guide on how to do it.

What’s Next?

We have successfully validated that the Import is ready to go!

Next, we will prepare the actual Migration package.

The Great Azure DevOps Migration – Part 2: Setup

The first step to a successful Azure DevOps migration is to setup your staging VM. I want to completely isolate my migration from my live TFS server.

If you missed the Introduction post, get caught up here.

I highly recommend Microsoft’s Azure DevOps Service Migration Guide.

Why a Staging VM?

  • I need to delete some code from my TFS repos before importing to Azure DevOps.
  • I need to make several changes to the project templates to pass validation. I don’t want any of these changes to affect my live TFS server in case I need to rollback.
  • I want the live TFS server to become my backup for the code I’m deleting, in case we ever need to access it again.

These requirements make it safest to completely isolate my staging VM from my live VM.

But First…

The very first thing that needs to be done is update your existing live TFS server to use the latest version of Azure DevOps Server. You need to be within the latest two versions to successfully migrate. So, before even starting this process, get your live TFS server up to date.

Setup the New VM

The first step is to setup a VM that will host the migration. The safest path is to not clone the existing VM, but setup a new VM from scratch. This is because cloning the VM will pull across paths pointing at your live TFS VM.


Save yourself some pain later and just install the latest Windows Server version. I originally used the version that my live TFS server was using (2012), but you’re going to need some tooling later on that requires later versions of Windows Server. So, just install the latest now, it’ll work fine.

You’re also going to need a ton of hard drive space. I ended up increasing the size of my server about 4 times during the process as I kept realizing I needed more. Just give it a ton of space to start. I set it to 1 TB for the final import.

SQL Server

Install the exact same version of SQL Server that the live TFS server is using. Install the Management Tools, too. You will need those later.

Install IIS

IIS is needed to access the new TFS install. Install this from Windows Features.

Install Azure DevOps Server

It is critical that you install the exact same Azure DevOps Server version that you are using on your live TFS server. I initially installed 2019, and then had to go back and install 2019.0.1. They have to match exactly.

After installation, close the startup dialog, we’re going to use a backup.

Take Full Backup of Live TFS Server

The best way to do this is to use the built-in SQL Backup tooling. I don’t actually use this on the live TFS server, but I wanted to use it for this process because it is easiest.

To make it work, just change the TFS databases on the live TFS server to FULL backup temporarily (if they are not already). In Scheduled Backups (on the live TFS server), use Take Full Backup Now.

When the backup is complete, copy it to the C drive of your new staging server.

Be sure to change your live TFS server’s backup settings to their initial settings if necessary.

Hosts File (If You’re Scared…)

If you are scared of accidentally impacting your live TFS server (like I definitely was), you can be extra safe by blocking access to your live TFS server from the staging migration server.

Open the hosts file in C:\Windows\System32\Drivers\Etc\ and add two lines: LIVE_SERVER_NAME LIVE_SERVER_NAME.DOMAIN.local

This is going to point any calls to your live TFS server back to your staging server.

Whew…. feels safer already!

Still Scared? Shutdown the Live TFS Server

If you’re still scared, you can also shutdown the live TFS server while you make the big changes, like deleting old code.

My biggest fear is that I’m accidentally logged into the incorrect VM and running commands on the live TFS server. Or I clicked a bookmark in my browser which unknowingly took me to the live TFS server.

For those reasons, it is probably worth shutting down the live TFS server during this process (if possible). If you can’t do that, just be very careful when deleting code.

Restore Backups

Back on the staging server, restore the backups on the C: by using the Azure DevOps Management Tool.

In Scheduled Backups, choose Restore Databases. This will handle the SQL restore for you.

Configure Azure DevOps Service

Now, in the Azure DevOps Configuration Center, configure the installation. Use the existing databases, and when asked, choose to Configure As A Clone. This will adjust all the URL’s inside the database so they do not point to your live TFS server.

I used the same service users for this TFS install as I used in my live TFS server, however to be extra safe, you could setup new users for this staging server.

Visual Studio 2019

The last step needed is to install Visual Studio 2019. This will be needed later to get access to the TFS commands the SSDT commands.

What’s Next?

We now have our staging migration server setup and we’re ready to start cleaning up the data to be imported.

In the next step, I’m going to eliminate the data that we don’t want to move to our new Azure DevOps Service. This will reduce the size of our import and give us a cleaner final setup.

The Great Azure DevOps Migration – Part 1: Introduction

wagons migrating west

This series is going to describe the process I went through to migrate my company’s on-premises TFS setup to Azure DevOps in the cloud. The process did turn out to be much more time-consuming than I anticipated, so hopefully this can help future migrators!

This guide will cover the issues I ran into with my setup, you should look at the Microsoft docs for any of your specific issues.

The guide will cover a full dry-run of the migration, and then the final live migration. You must do a dry run first!

On Premises

I’ll start by describing my current on-premises setup, and what I expect my final migrated setup to look like.


We transitioned from Visual SourceSafe to TFS 2008 about 10 years ago. Since the initial installation, we have been really good about updating to the latest version of TFS as it was released.

So, our current version of on-premises TFS is running Azure DevOps Server 2019.0.0. TFS was renamed to Azure DevOps Server this year, but it’s still just TFS with a fancier name.

If you haven’t kept your TFS version up to date, you are going to need to upgrade it to the latest version of on-premises TFS before starting this process.


We have a single TFS collection named DefaultCollection. When migrating to Azure DevOps, each collection gets migrated as a separate account, so having a single collection is the easiest path forward if you have a small team.


Inside each Collection, you can have multiple Projects. Each Project can have its own Process template and Project settings. We have about 50 projects, but we actually only use one. When we migrated from SourceSafe to TFS 10 years ago, the migration tool converted each project (per application) into an individual TFS project.

Over time, we consolidated the active projects into a single TFS project. So, only one of the 50 projects is under active development, the rest are legacy apps or abandoned apps that are never modified.

For the move to Azure DevOps, I will be moving only the active TFS Project and leaving the old projects behind. If we need those projects in the future, I will move just their current code base into a new Azure DevOps GIT repository.


GIT did not exist in TFS when we started using it, so about 4 years ago (?) we migrated all of our active code-bases in the active project to use GIT repos instead of TFVC. We did this inside the current project, so that we could maintain our existing Work Items. That means we currently have a Project containing a TFVC repository and multiple GIT repositories.

For the move to Azure DevOps, I am going to only migrate the GIT repositories, so I will need to remove the TFVC repository before completing the import.


We already have an account in Azure. We don’t host our entire application infrastructure in Azure, but we do host some services there, so we have active subscriptions.

Build Servers

We host two TFS build servers locally. For a few of our applications, we have third-party dependencies that need to be installed on the build server, but the majority of our applications could be built from a non-custom build server.

For now, I plan to use our existing local build servers for all builds, but long-term we should be able to migrate many of our apps to be built in the Azure DevOps service.


We have made some changes to the TFS Process. Mostly, we’ve added fields to work items, modified the work item UI, and we’ve added a few extra work item types.

I believe it will all import smoothly, as we have not made any extreme changes to the Process.

What’s Next?

In the next post, I will cover setting up the new VM to host the staged TFS installation for migration.

  1. Introduction
  2. Setup the Staging VM
  3. Purge Unnecessary Data
  4. Validate the Migration
  5. Prepare the Migration
  6. Migration Dry Run
  7. Live Migration
  8. Conclusion