DEV Community

DevOps Start
DevOps Start

Posted on • Originally published at devopsstart.com

Azure DevOps to GitHub Migration: An AI-Driven Playbook

If you are moving repositories from Azure DevOps to GitHub, the tool you want is the gh ado2gh extension of the GitHub CLI, part of GitHub Enterprise Importer (GEI). It migrates Git history, branches, and pull requests from Azure DevOps Services to GitHub Enterprise Cloud in one command per repo. What it does not touch: Azure Boards work items, Azure Pipelines, Azure Artifacts, and wikis. Those need separate tools or a manual plan. Get that split clear before you write a single migration script, because most failed migrations are not technical failures. They are teams that assumed one tool moved everything and found out on cutover day that it did not.

The reason this migration is worth doing in 2026 is not just consolidation. It is that the AI tooling on the GitHub side, specifically the Copilot coding agent, only works against repositories that live on GitHub. If your code sits in Azure Repos, you are locked out of agentic workflows that can now open pull requests, run your tests, and self-review a patch before a human ever looks at it. That is the real incentive, and it changes how you should plan the move.

What GEI actually migrates (and what it drops)

Be precise here, because the gap is where teams get burned. GitHub Enterprise Importer, when pointed at Azure DevOps, moves the following:

  • Git source, including full commit history and all branches
  • Pull requests, both active and merged, with their comments
  • User history and attribution on commits
  • Work item links that were attached to pull requests
  • Attachments and branch policies

It does not move:

  • Azure Boards work items. There is no built-in path from Boards to GitHub Issues. You export and re-import, or you leave history in a read-only Azure project.
  • Azure Pipelines. These need the separate GitHub Actions Importer tool, which forecasts and partially automates the conversion to GitHub Actions workflows.
  • Azure Artifacts feeds. You download existing packages, repoint your package source at GitHub Packages, and republish.
  • Wikis. Manual export, or clone the wiki Git repo and push it as a normal repo.

One more sharp edge: GEI migrates Azure DevOps Services (the cloud product), not Azure DevOps Server (the on-prem product). If you are still on Server, you have to get to Services first or use a different path entirely. And abandoned pull requests whose branches were already deleted do not come across, so if audit history matters to you, snapshot it before cutover.

The official Azure DevOps to GitHub migration docs are the source of truth for the current feature matrix, and it does shift, so check it against your own inventory rather than trusting a blog post's list six months from now.

Step 1: inventory before you touch anything

Do not start with a migration command. Start with an inventory. You cannot plan waves, estimate effort, or spot the repos nobody has committed to in three years without one.

Install the extension and generate a report:

$ gh extension install github/gh-ado2gh
$ export ADO_PAT="your-azure-devops-token"
$ export GH_PAT="your-github-token"
$ gh ado2gh inventory-report --ado-org YOUR_ADO_ORG
Enter fullscreen mode Exit fullscreen mode

The inventory-report command hits the Azure DevOps API and writes CSV files covering organizations, projects, repositories, and pipelines. Read them. You are looking for three things: repos small enough to migrate in the first pilot wave, repos with heavy pipeline coupling that will need Actions conversion, and dead repos you should archive instead of move. The token you use for this needs full access, so create a dedicated one and revoke it when the migration is done.

If you have never run a live cutover before, the GitHub Actions security guide is worth reading first, because the moment your code lands on GitHub, its secrets handling model changes and the old Azure variable groups do not come with it.

Step 2: create the personal access tokens

Both PATs need the right scopes or the migration fails halfway, which is worse than failing at the start. On the Azure side, the ADO_PAT needs read access to code and, if you want work item links and board integration, full access. On the GitHub side, the GH_PAT needs repo, admin:org, and workflow scopes at minimum for a repository migration into an org.

Set them as environment variables so they do not end up in your shell history as literals:

$ read -rs ADO_PAT && export ADO_PAT
$ read -rs GH_PAT && export GH_PAT
Enter fullscreen mode Exit fullscreen mode

The read -rs pattern keeps the token off the screen and out of history. Small thing, but on a migration you are handling org-admin credentials, so treat them like it.

Step 3: generate and run the migration script

For anything beyond one or two repos, do not hand-write migrate-repo calls. Let the tooling generate them:

$ gh ado2gh generate-script --ado-org YOUR_ADO_ORG --github-org YOUR_GH_ORG --all
Enter fullscreen mode Exit fullscreen mode

This produces a PowerShell script, migrate.ps1, with one migration call per repository it found. Open it before you run it. The generated script is a starting point, not gospel, and there are known cases where you need to edit repo name mappings or split it into waves. This is the moment to remove the dead repos you flagged in the inventory and to reorder so your pilot team's repos go first.

A single repository migration, if you want to run one by hand to test the path, looks like this:

$ gh ado2gh migrate-repo --ado-org YOUR_ADO_ORG --ado-team-project YOUR_PROJECT --ado-repo YOUR_REPO --github-org YOUR_GH_ORG --github-repo YOUR_REPO
Enter fullscreen mode Exit fullscreen mode

Migrations are queued server-side and run asynchronously, so the command returns a migration ID rather than blocking until the repo is fully copied. Pull the logs afterward with the importer's log command to confirm history and pull requests came across cleanly. Do not mark a repo done because the command exited zero. Check the log.

Step 4: pipelines are a separate project

This is where teams underestimate the work. Your Azure Pipelines do not migrate with GEI. GitHub Actions Importer is a distinct tool that audits your existing pipelines, forecasts how much converts automatically, and generates draft GitHub Actions workflows.

Expect the audit to tell you that maybe 70 to 80 percent of a typical pipeline converts mechanically, and the rest, custom tasks, marketplace extensions, and complex approval gates, needs hand translation. A converted workflow lands as a YAML file in .github/workflows/:

name: CI
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build and test
        run: |
          npm ci
          npm test
Enter fullscreen mode Exit fullscreen mode

Budget real engineering time for the pipeline conversion. If you already run infrastructure-as-code reviews through Actions, the pattern in how to automate Terraform reviews with GitHub Actions shows the shape of a mature Actions pipeline you are converging toward, not the thin line-by-line port the importer gives you first.

Step 5: turn on the AI tooling you migrated for

Here is the payoff. Once a repository lives on GitHub, the Copilot coding agent can work it like a background peer developer. You assign it an issue, it spins up its own environment powered by GitHub Actions, makes changes, runs your tests, and opens a pull request. As of 2026 it also runs Copilot code review against its own diff before it asks for human eyes, so the patch that reaches you has already been through one revision loop.

The guardrails matter and they are sensible defaults. The agent can only push to branches it creates, conventionally copilot/*, so your main and team-managed branches stay untouched. Every pull request still needs independent human review because the agent cannot approve or merge its own work. And CI in GitHub Actions will not run on the agent's PR without your approval. Those three rules are why enterprises can actually turn this on.

You can go further with custom agents. Drop a file under .github/agents/ to codify a repeatable approach, for example a performance agent told to benchmark first, make the change, then measure the difference before opening the PR:

name: perf-optimizer
description: Benchmarks, optimizes a hot path, then verifies the improvement.
instructions: |
  Run the existing benchmark suite and record the baseline.
  Make the smallest change that improves the target metric.
  Re-run the benchmark and include before-and-after numbers in the PR body.
Enter fullscreen mode Exit fullscreen mode

For governing what these agents are allowed to touch across an org, the approach in governing AI agents in CI/CD with OPA and MCP maps cleanly onto GitHub's own AI Controls, which give enterprise admins a central page to enable or disable the coding agent, code review, and custom agents per organization.

If your developers are still deciding which assistant to standardize on inside the editor, the tradeoffs in Cursor vs Copilot vs Cody are worth reading, but note that the coding agent described here is a GitHub-native background worker, not an in-editor completion tool, and it is one of the concrete capabilities you gain by being on GitHub in the first place.

How to sequence the rollout

Do not big-bang a large org. The pattern that works is waves:

  1. Pilot wave. Pick one team with a handful of small, low-risk repos and light pipeline coupling. Migrate their repos, convert their pipelines, and have them work on GitHub for two weeks. Fix what breaks.
  2. Early adopters. Expand to teams that asked for the AI tooling. Their motivation carries them through the rough edges, and their feedback tunes your generated scripts.
  3. Long tail. Everyone else, in batches sized to what your team can support in a week. Archive dead repos instead of migrating them.

Keep the Azure DevOps org in read-only mode for a defined window after each wave rather than deleting it. You will need to reference old work items and abandoned PRs that did not migrate, and a read-only source is cheap insurance against a rollback you did not plan for.

The verdict

The Git migration itself is the easy part. One generate-script, one reviewed run, and your history is on GitHub with pull requests intact. The work that decides whether the migration succeeds is everything GEI does not do: converting pipelines to Actions, deciding what happens to Boards and Artifacts, and rolling out in waves small enough to recover from. Do the inventory first, treat pipelines as their own project, and keep the old org read-only until you are sure.

The reason to spend that effort is not tidiness. It is that the AI development tooling, the coding agent that opens and self-reviews pull requests, only exists for code that lives on GitHub. Migrating the repos is the price of entry to agentic development, and in 2026 that is a price a lot of enterprises have decided is worth paying.

Top comments (0)