{"meta":{"title":"Migrating your repository with Enterprise Live Migrations","intro":"Migrate from GitHub Enterprise Server to GHE.com with minimal downtime.","product":"Migrations","breadcrumbs":[{"href":"/en/enterprise-cloud@latest/migrations","title":"Migrations"},{"href":"/en/enterprise-cloud@latest/migrations/elm","title":"Live migrations (GHES to GHE.com)"},{"href":"/en/enterprise-cloud@latest/migrations/elm/migrate-your-repository","title":"Migrate your repository"}],"documentType":"article"},"body":"# Migrating your repository with Enterprise Live Migrations\n\nMigrate from GitHub Enterprise Server to GHE.com with minimal downtime.\n\n> \\[!TIP] As you follow this guide, you can refer to the [Enterprise Live Migrations CLI reference](/en/enterprise-cloud@latest/migrations/elm/elm-cli-reference) for more detailed usage information. If you encounter errors, see [Troubleshooting live migrations from GitHub Enterprise Server to GHE.com](/en/enterprise-cloud@latest/migrations/elm/troubleshooting).\n\n## Prerequisites\n\nMake sure your environments and developers are ready for the migration. See [Preparing for your live migration from GitHub Enterprise Server to GHE.com](/en/enterprise-cloud@latest/migrations/elm/prepare-for-your-migration).\n\n## 1. Configure GitHub Enterprise Server\n\nYou must set some configuration on the GitHub Enterprise Server instance before creating tokens and performing a migration. These configuration values apply to all ELM migrations. Developers on GitHub Enterprise Server may experience a brief downtime when you apply the new configuration.\n\n1. Access the GitHub Enterprise Server administrative shell over SSH. See [Accessing the administrative shell (SSH)](/en/enterprise-server@3.22/admin/administering-your-instance/administering-your-instance-from-the-command-line/accessing-the-administrative-shell-ssh).\n\n2. Set the following configuration variables with `ghe-config`.\n\n   For example: `ghe-config app.elm-exporter.enabled true`\n\n   | Variable                                             | Set this to...                                                                                                                                                                                                                                                          |\n   | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n   | `app.elm-exporter.enabled`                           | `true`                                                                                                                                                                                                                                                                  |\n   | `app.elm.internal-webhooks-enabled`                  | `true`                                                                                                                                                                                                                                                                  |\n   | `app.elm-exporter.webhooks-loopback-address-enabled` | `true`                                                                                                                                                                                                                                                                  |\n   | `secrets.elm-exporter.migration-target-url`          | The API URL for your destination enterprise (for example: `https://api.octocorp.ghe.com`). Do **not** include a trailing slash at the end of the URL.                                                                                                                   |\n   | `secrets.elm-exporter.source-user`                   | The username associated with the operator's GitHub Enterprise Server token. This should be your username on GitHub Enterprise Server; if someone else is going to create this token, the value here should be set to their username. We recommend the `ghe-admin` user. |\n\n3. Apply the configuration.\n\n   ```shell copy\n   ghe-config-apply\n   ```\n\n4. Leave the SSH session. You will run the rest of the commands in a local terminal session.\n\n## 2. Create operator tokens with enterprise access\n\nThe operator must authenticate to both the source and destination enterprise with a personal access token (classic). For instructions on creating tokens, see [Managing your personal access tokens](/en/enterprise-cloud@latest/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic).\n\n**Ensure that you make a note of both tokens**, as you will need them in the next step.\n\n1. On **GitHub Enterprise Server**, create a personal access token (classic) and select the required scope:\n\n   * `admin:enterprise`\n\n   You will use this token as the **Source token** when configuring the ELM CLI.\n\n2. On **GHE.com**, create a personal access token (classic) and select the required scopes:\n\n   * `admin:enterprise`\n   * `admin:org`\n\n   You will use this token as the **Target token** when configuring the ELM CLI.\n\n## 3. Configure the ELM command line tool\n\nYou will run the migration from a local terminal session, using an extension of the GitHub CLI.\n\n1. Install the [GitHub CLI](https://cli.github.com/) on your local machine. You must be using version 2.0 or later.\n\n2. Install the ELM extension.\n\n   ```shell copy\n   gh extension install github/gh-elm\n   ```\n\n3. Launch the installation wizard to configure the extension.\n\n   ```shell copy\n   gh elm configure\n   ```\n\n4. Follow the instructions in the installation wizard, providing the API URLs (for example: `https://api.SUBDOMAIN.ghe.com`) for your source and destination and the tokens you created in the previous step.\n\nAny of these values can also be provided as CLI flags on any `gh elm` command, which will take priority over the configuration. For example: `--target-url https://api.SUBDOMAIN.ghe.com`.\n\nThis setup process will store the URLs in a platform-specific configuration file in your operating system's configuration directory, at `gh-elm/config.json`. The access tokens will be securely stored in your computer's secret storage.\n\n## 4. Configure the live migration secrets\n\nIn addition to the operator tokens with enterprise access, you must create a personal access token (classic) for the source and target organizations. You must repeat these steps for every organization you are migrating from.\n\n### Create access tokens\n\nELM must authenticate with a personal access token (classic) for both the source and destination of the migration. For instructions on creating tokens, see [Managing your personal access tokens](/en/enterprise-cloud@latest/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic).\n\n**Ensure that you make a note of these tokens**, as you will need them in the next step.\n\n1. Create a personal access token (classic) on **GitHub Enterprise Server** with the following scopes:\n\n   * `repo`\n   * `admin:org`\n   * `admin:repo_hook`\n   * `admin:org_hook`\n\n   This is your source token.\n\n2. Create a personal access token (classic) on **GHE.com** with the following scopes:\n\n   * `repo`\n   * `workflow`\n   * `admin:org`\n   * `admin:repo_hook`\n   * `admin:enterprise`\n\n   This is your target token.\n\n   > \\[!IMPORTANT]\n   > If single sign-on is enforced on the target organization on GHE.com, you must authorize the GHE.com token for SSO.\n\n### Configure your organization's ELM secrets\n\nUse the `gh elm config` commands to set the source and target access tokens:\n\n1. Set the source token.\n\n   ```shell copy\n   gh elm config set-source-pat EXISTING-GHES-ORG\n   ```\n\n   Paste the source token into the terminal when asked.\n\n2. Set the target token.\n\n   ```shell copy\n   gh elm config set-target-pat EXISTING-GHES-ORG\n   ```\n\n   Paste the target token into the terminal when asked.\n\nYou can also set the tokens interactively, using `gh elm config org-tokens EXISTING-GHES-ORG`, or in your organization settings at `https://GHES_HOSTNAME/organizations/EXISTING-GHES-ORG/settings/secrets/elm-exporter/`.\n\n## 5. Create a migration\n\nCreate a new migration by specifying the source and target repository details.\n\n> \\[!NOTE] The `target-org` can be new or existing. If the target organization doesn't already exist, it will be created during the migration. However, no settings from the source organization will be migrated.\n\n```shell copy\ngh elm migration create \\\n  --source-org EXISTING-GHES-ORG \\\n  --source-repo EXISTING-GHES-REPO \\\n  --target-org GHEC-ORG \\\n  --target-repo NEW-GHEC-REPO\n```\n\nFor example:\n\n```shell\ngh elm migration create \\\n  --source-org my-ghes-org \\\n  --source-repo my-ghes-repo \\\n  --target-org my-dr-org \\\n  --target-repo my-dr-repo\n```\n\nOptional flags:\n\n* `--start`: If you're ready to start the migration immediately.\n* `--target-visibility`: Migrated repositories are created with **internal** visibility by default, but you can specify `private`.\n\n### Save the migration ID\n\nYou should see a response like the following:\n\n```json\n{\n  \"migrationId\": \"2b5c9eae-b5da-4306-ab04-2a29cc2b7cb9\",\n  \"expiresAt\": \"2026-02-11T21:49:33.619162159Z\"\n}\n```\n\nExport the `migrationId` as a variable, as you will need it for the next commands. For example:\n\n```shell\nexport MIGRATION_ID='2b5c9eae-b5da-4306-ab04-2a29cc2b7cb9'\n```\n\n## 6. Start the migration\n\nIf you didn't already start the migration, start it now using the migration ID you just saved.\n\n```shell copy\ngh elm migration start --migration-id $MIGRATION_ID\n```\n\nThis launches the backfill and live update processes. ELM is now collecting data from the source repository and listening for supported webhook events.\n\n## 7. Monitor the migration\n\nWhen the migration has started, you should see a new repository on GHE.com. During the migration, you will see the repository fill with an initial load of data and receive updates as developers continue to work in the source repository.\n\nYou can monitor the progress of the migration interactively using the `watch` command:\n\n```shell\ngh elm migration watch $MIGRATION_ID\n```\n\nThis will poll the migration status API and display a self-refreshing text UI that reflects the current progress.\n\n### Programmatic monitoring using `migration status`\n\nIf you want a migration status suitable for automation, use the `status` command:\n\n```shell copy\ngh elm migration status --migration-id $MIGRATION_ID\n```\n\nThe most important indicator in the response is the status in the **combinedState** object. When the status reaches `COMBINED_STATUS_READY_FOR_CUTOVER`, you should be ready to proceed to the next step. However, you will be alerted in the `displayMessage` if any individual resources failed to migrate, which you may need to investigate.\n\nFor example:\n\n```json\n  \"combinedState\":  {\n    \"status\":  \"COMBINED_STATUS_READY_FOR_CUTOVER\",\n    \"displayMessage\":  \"Ready for cutover (1 resources failed)\",\n    \"repositories\":  [\n      {\n        \"repositoryNwo\":  \"new-test-org/my-new-repo\",\n        \"phase\":  \"REPOSITORY_PHASE_READY_FOR_CUTOVER\",\n        \"displayStatus\":  \"Ready for cutover (1 failed)\"\n      }\n    ],\n    \"readyForCutover\":  true,\n    \"cutoverBlockers\":  []\n  },\n```\n\nTips:\n\n* If you're running multiple migrations, you can check the status of all of them with `gh elm migration list`. This command shows in-progress migrations by default, but you can also filter by `--status`.\n* If you encounter failure statuses that require attention, see [Troubleshooting live migrations from GitHub Enterprise Server to GHE.com](/en/enterprise-cloud@latest/migrations/elm/troubleshooting#statuses-and-recommended-actions).\n\n## 8. Complete the migration\n\nWhen a migration is ready for cutover, you can complete the migration. The cutover process will archive the source repository, making it **permanently read-only** unless a repository administrator unarchives it.\n\n```shell copy\ngh elm migration cutover --migration-id $MIGRATION_ID\n```\n\nContinue to monitor the migration. When you see the `MIGRATION_STATUS_COMPLETED` status at the top of the response, the migration is complete, although there are some follow-up tasks to give access to users from GitHub Enterprise Server.\n\n## Next steps\n\nGive users access to the new repository and reconcile activity with user accounts. See [Completing your live migration from GitHub Enterprise Server to GHE.com](/en/enterprise-cloud@latest/migrations/elm/complete-your-migration)."}