You can run your migration with either the CLI or the API.
The CLI simplifies the migration process and is recommended for most customers. Advanced customers with heavy customization needs can use the API to build their own integrations with Enterprise Importer.
- We strongly recommend that you perform a trial run of your migration and complete your production migration soon after. To learn more about trial runs, see Overview of a migration from Azure DevOps to Enterprise Cloud.
- Ensure you understand the data that will be migrated and the known support limitations of the Importer. For more information, see About migrations from Azure DevOps to Enterprise Cloud.
- While not required, we recommend halting work during your production migration. The Importer doesn't support delta migrations, so any changes that happen during the migration will not migrate. If you choose not to halt work during your production migration, you'll need to manually migrate these changes.
- For the destination organization on , you need to be an organization owner or have the migrator role. For more information about the migrator role, see Managing access for a migration from Azure DevOps.
To make GraphQL queries, you'll need to write your own scripts or use an HTTP client like Insomnia.
To learn more about getting started with the GraphQL API, including how to authenticate, see Forming calls with GraphQL.
You will send all GraphQL queries to the destination of your migration. If you're migrating to Enterprise Cloud with data residency, make sure to send queries to the endpoint for your enterprise's subdomain of GHE.com.
As an organization owner in Enterprise Cloud, use the GetOrgInfo
query to return the ownerId
, also called the organization ID, for the organization you want to own the migrated repositories. You'll need the ownerId
to identify your migration destination.
query(
$login: String!
){
organization (login: $login)
{
login
id
name
databaseId
}
}
Query variable | Description |
---|---|
login | Your organization name. |
{
"data": {
"organization": {
"login": "Octo",
"id": "MDEyOk9yZ2FuaXphdGlvbjU2MTA=",
"name": "Octo-org",
"databaseId": 5610
}
}
}
In this example, MDEyOk9yZ2FuaXphdGlvbjU2MTA=
is the organization ID or ownerId
, which we'll use in the next step.
You can set up a migration source using the createMigrationSource
query. You'll need to supply the ownerId
, or organization ID, gathered from the GetOrgInfo
query.
Your migration source is your ADO organization.
mutation createMigrationSource($name: String!, $ownerId: ID!) {
createMigrationSource(input: {name: $name, url: "https://dev.azure.com", ownerId: $ownerId, type: AZURE_DEVOPS}) {
migrationSource {
id
name
url
type
}
}
}
Note
Make sure to use AZURE_DEVOPS
for type
.
Query variable | Description |
---|---|
name | A name for your migration source. This name is for your own reference, so you can use any string. |
ownerId | The organization ID of your organization on Enterprise Cloud. |
{
"data": {
"createMigrationSource": {
"migrationSource": {
"id": "MS_kgDaACQxYmYxOWU4Yi0wNzZmLTQ3NTMtOTdkZC1hNGUzZmYxN2U2YzA",
"name": "Azure Devops Source",
"url": "https://dev.azure.com",
"type": "AZURE_DEVOPS"
}
}
}
}
In this example, MS_kgDaACQxYmYxOWU4Yi0wNzZmLTQ3NTMtOTdkZC1hNGUzZmYxN2U2YzA
is the migration source ID, which we'll use in the next step.
When you start a migration, a single repository and its accompanying data migrates into a brand new repository that you identify.
If you want to move multiple repositories at once from the same source organization, you can queue multiple migrations. You can run up to 5 repository migrations at the same time.
mutation startRepositoryMigration (
$sourceId: ID!,
$ownerId: ID!,
$sourceRepositoryUrl: URI!,
$repositoryName: String!,
$continueOnError: Boolean!,
$accessToken: String!,
$Pat: String!,
$targetRepoVisibility: String!
){
startRepositoryMigration( input: {
sourceId: $sourceId,
ownerId: $ownerId,
repositoryName: $repositoryName,
continueOnError: $continueOnError,
accessToken: $accessToken,
Pat: $Pat,
targetRepoVisibility: $targetRepoVisibility
sourceRepositoryUrl: $sourceRepositoryUrl,
}) {
repositoryMigration {
id
migrationSource {
id
name
type
}
sourceUrl
}
}
}
Query variable | Description |
---|---|
sourceId | Your migration source id returned from the createMigrationSource mutation. |
ownerId | The organization ID of your organization on Enterprise Cloud. |
repositoryName | A custom unique repository name not currently used by any of your repositories owned by the organization on Enterprise Cloud. An error-logging issue will be created in this repository when your migration is complete or has stopped. |
continueOnError | Migration setting that allows the migration to continue when encountering errors that don't cause the migration to fail. Must be true or false . We highly recommend setting continueOnError to true so that your migration will continue unless the Importer can't move Git source or the Importer has lost connection and cannot reconnect to complete the migration. |
Pat | The personal access token for your destination organization on Enterprise Cloud. |
accessToken | The personal access token for your source. |
targetRepoVisibility | The visibility of the new repository. Must be private , public , or internal . If not set, your repository is migrated as private. |
sourceRepositoryUrl | The URL of your source repository, using the format https://dev.azure.com/{organization}/{project}/_git/{repository} . |
For personal access token requirements, see Managing access for a migration from Azure DevOps.
In the next step, you'll use the migration ID returned from the startRepositoryMigration
mutation to check the migration status.
To detect any migration failures and ensure your migration is working, you can check your migration status using the getMigration
query. You can also check the status of multiple migrations with getMigrations
.
The getMigration
query will return with a status to let you know if the migration is queued
, in progress
, failed
, or completed
. If your migration failed, the Importer will provide a reason for the failure.
query (
$id: ID!
){
node( id: $id ) {
... on Migration {
id
sourceUrl
migrationSource {
name
}
state
failureReason
}
}
}
Query variable | Description |
---|---|
id | The id of your migration that the startRepositoryMigration mutation returned. |
To finish your migration, we recommend that you check the "Migration Log" issue. This issue is created on in the destination repository.
Finally, we recommend that you review your migrated repositories for a soundness check.
If this is your first migration, you'll need to install the ADO2GH extension of the CLI. For more information about CLI, see About CLI.
Alternatively, you can download a standalone binary from the releases page for the /gh-ado2gh
repository. You can run this binary directly, without the gh
prefix.
Install the CLI. For installation instructions for CLI, see the CLI repository.
Note
You need version 2.4.0 or newer of CLI. You can check the version you have installed with the
gh --version
command.Install the ADO2GH extension.
Shell gh extension install /gh-ado2gh
gh extension install /gh-ado2gh
Any time you need help with the ADO2GH extension, you can use the --help
flag with a command. For example, gh ado2gh --help
will list all the available commands, and gh ado2gh migrate-repo --help
will list all the options available for the migrate-repo
command.
The ADO2GH extension of the CLI is updated weekly. To make sure you're using the latest version, update the extension.
gh extension upgrade /gh-ado2gh
gh extension upgrade /gh-ado2gh
Before you can use the ADO2GH extension to migrate to Enterprise Cloud, you must create personal access tokens that can access the source and destination organizations, then set the personal access tokens as environment variables.
Create and record a personal access token (classic) that will authenticate for the destination organization on Enterprise Cloud, making sure that the token meets all requirements. For more information, see Managing access for a migration from Azure DevOps.
Create and record a personal access token that will authenticate for the source organization on Azure DevOps, making sure that this token meets all requirements. For more information, see Managing access for a migration from Azure DevOps.
Set environment variables for the personal access tokens, replacing TOKEN in the commands below with the personal access tokens you recorded above. Use
GH_PAT
for the destination organization andADO_PAT
for the source organization.If you're using Terminal, use the
export
command.Shell export GH_PAT="TOKEN" export ADO_PAT="TOKEN"
export GH_PAT="TOKEN" export ADO_PAT="TOKEN"
If you're using PowerShell, use the
$env
command.Shell $env:GH_PAT="TOKEN" $env:ADO_PAT="TOKEN"
$env:GH_PAT="TOKEN" $env:ADO_PAT="TOKEN"
If you're migrating to Enterprise Cloud with data residency, for convenience, set an environment variable for the base API URL for your enterprise.
If you're using Terminal, use the
export
command.Shell export TARGET_API_URL="https://api.octocorp.ghe.com"
export TARGET_API_URL="https://api.octocorp.ghe.com"
If you're using PowerShell, use the
$env
command.Shell $env:TARGET_API_URL="https://api.octocorp.ghe.com"
$env:TARGET_API_URL="https://api.octocorp.ghe.com"
You'll use this variable with the
--target-api-url
option in commands you run with the CLI.
If you want to migrate multiple repositories to Enterprise Cloud at once, use the CLI to generate a migration script. The resulting script will contain a list of migration commands, one per repository.
Note
Generating a script outputs a PowerShell script. If you're using Terminal, you will need to output the script with the .ps1
file extension and install PowerShell for either Mac or Linux to run it.
If you want to migrate a single repository, skip to the next step.
To generate a migration script, run the gh ado2gh generate-script
command.
gh ado2gh generate-script --ado-org SOURCE ---org DESTINATION --output FILENAME
gh ado2gh generate-script --ado-org SOURCE ---org DESTINATION --output FILENAME
Replace the placeholders in the command above with the following values.
Placeholder | Value |
---|---|
SOURCE | Name of the source organization |
DESTINATION | Name of the destination organization |
FILENAME | A filename for the resulting migration script If you're using Terminal, use a .ps1 file extension as the generated script requires PowerShell to run. You can install PowerShell for Mac or Linux. |
Argument | Description |
---|---|
--target-api-url TARGET-API-URL | If you're migrating to GHE.com, add --target-api-url TARGET-API-URL , where TARGET-API-URL is the base API URL for your enterprise's subdomain. For example: https://api.octocorp.ghe.com . |
--all | Add additional functionality to the script, such as rewiring pipelines, creating teams, and configuring Azure Boards integrations. |
--download-migration-logs | Download the migration log for each migrated repository. For more information about migration logs, see Accessing your migration logs for Enterprise Importer. |
After you generate the script, review the file and, optionally, edit the script.
- If there are any repositories you don't want to migrate, delete or comment out the corresponding lines.
- If you want any repositories to have a different name in the destination organization, update the value for the corresponding
--target-repo
flag. - If you want to change the visibility of new repository, update the value for the corresponding
--target-repo-visibility
flag. By default, the script sets the same visibility as the source repository.
If you downloaded ADO2GH as a standalone binary rather than as an extension for the CLI, you will need to update your generated script to run the binary instead of gh ado2gh
.
You can migrate multiple repositories with a migration script or a single repository with the gh ado2gh migrate-repo
command.
To migrate multiple repositories, run the script you generated above. Replace FILENAME in the commands below with the filename you provided when generating the script.
If you're using Terminal, use
./
.Shell ./FILENAME
./FILENAME
If you're using PowerShell, use
.\
.Shell .\FILENAME
.\FILENAME
To migrate a single repository, use the gh ado2gh migrate-repo
command.
gh ado2gh migrate-repo --ado-org SOURCE --ado-team-project TEAM-PROJECT --ado-repo CURRENT-NAME ---org DESTINATION ---repo NEW-NAME
gh ado2gh migrate-repo --ado-org SOURCE --ado-team-project TEAM-PROJECT --ado-repo CURRENT-NAME ---org DESTINATION ---repo NEW-NAME
Note
If you're migrating to GHE.com, add --target-api-url TARGET-API-URL
, where TARGET-API-URL is the base API URL for your enterprise's subdomain. For example: https://api.octocorp.ghe.com
.
Replace the placeholders in the command above with the following values.
Placeholder | Value |
---|---|
SOURCE | Name of the source organization |
CURRENT-NAME | The name of the repository you want to migrate |
DESTINATION | Name of the destination organization |
NEW-NAME | The name you want the migrated repository to have |
TEAM-PROJECT | Name of the team project of the repository you want to migrate |
If you want to cancel a migration, use the abort-migration
command, replacing MIGRATION-ID with the ID returned from migrate-repo
.
gh ado2gh abort-migration --migration-id MIGRATION-ID
gh ado2gh abort-migration --migration-id MIGRATION-ID
When your migration is complete, we recommend reviewing your migration log. For more information, see Accessing your migration logs for Enterprise Importer.
We recommend that you review your migrated repositories for a soundness check.