◀ Playbook index
NO.31

🚚 Migrations

Updated: 2026-10-27

In a nutshell

EMU ↔ non-EMU is not a setting. It is a migration to a new enterprise, done with GEI.

GHES → GHE.com: move the repos that can't stop with ELM (live migration), and the rest with GEI.

Migration paths at a glance 📖 Docs

The four cases are the columns. Press + to open the aspect you need.

ToolGEI / ELMDocs
Non-EMU → EMUEMU → Non-EMUGHES → GHE.com (ELM)GHES → GHE.com (GEI)
ToolGEI (GitHub Enterprise Importer)ELM (Enterprise Live Migrations, GA 2026-09)GEI
Commandgh gei migrate-org or gh gei migrate-repogh elmgh gei migrate-repo
Scopeorg or repoDocs
Non-EMU → EMUEMU → Non-EMUGHES → GHE.com (ELM)GHES → GHE.com (GEI)
UnitWhole org (up to 5,000 repos) or one repo at a timeOne repo per migrationRepo by repo only (no org-level migration from GHES)
TeamsAn org migration moves teams and their repo access (not team membership)Not migrated. Recreate them on the target
DowntimeELM: minutesDocs
Non-EMU → EMUEMU → Non-EMUGHES → GHE.com (ELM)GHES → GHE.com (GEI)
Work freezeFreeze work during the migration (no delta sync)Cutover only (minutes). The source repo stays usable until thenFreeze each repo while it migrates
PrerequisitesEnterprise / identity / PATDocs
Non-EMU → EMUEMU → Non-EMUGHES → GHE.com (ELM)GHES → GHE.com (GEI)
TargetNew EMU enterpriseNew enterprise with personal accountsEnterprise on GHE.com (EMU required)
IdentityIdP with SAML / OIDC + SCIMPersonal accounts (SAML optional)IdP with SAML / OIDC + SCIM
OperatorSource org owner (or migrator role) + target enterprise ownerGHES site admin + GHE.com enterprise ownerSource org owner + target migrator role
TokensClassic PATs on both source and target
EnvironmentAvoid org name clashes (rename)GHES 3.17+, HTTPS, outbound access, migrations onGHES 3.4.1+, blob storage
Not migratedReconfigure by handDocs
Non-EMU → EMUEMU → Non-EMUGHES → GHE.com (ELM)GHES → GHE.com (GEI)
ExcludedTeam membership, Actions secrets / variables / runners, Packages, Projects, GitHub Apps, rulesets, custom properties, security alerts, LFS objects, PATs / SSH keys, user-owned reposOrg settings, teams, Projects, org webhooks, rulesets, PRs from forks, pending reviewsSame as GEI on the left
PartialSome branch protection rulesBranch protection (allowed actors and bypasses are dropped)Some branch protection rules
Limits40 GiB / 2 GBDocs
Non-EMU → EMUEMU → Non-EMUGHES → GHE.com (ELM)GHES → GHE.com (GEI)
SizePer repo: 40 GiB Git + 40 GiB metadata (public preview), 400 MiB per fileBuilt for large monorepos. Release assets up to 2 GB each40 GiB on GHES 3.13+ (lower on older versions)
OtherOrg migrations: up to 5,000 repos10 concurrent per GHES instance, 20 per target enterprise. Avoid force pushes while migratingComplex repos over about 40 GB: Expert Services recommended
After migrationReclaim mannequinsDocs
Non-EMU → EMUEMU → Non-EMUGHES → GHE.com (ELM)GHES → GHE.com (GEI)
UsersReclaim mannequins to managed users, sync teams from the IdPReclaim mannequins to personal accounts, add team membersReclaim mannequins to managed users, sync teams from the IdP
SettingsUsers recreate PATs / SSH keys, switch billing away from the old enterpriseRecreate org settings and teams, review branch protectionsRecreate teams and repo access

What isn’t possible 📖 Docs

None of these shortcuts work, whatever the case.

❌ Not possible✅ Do this instead
Switch an enterprise between EMU and non-EMU in placeCreate a new enterprise and migrate with GEI
”Transfer organization” into or out of an EMU enterpriseGEI migrate-org
Use ghe-migrator to reach the cloud (GHES → GHES only)GEI or ELM
Use ELM to reach GitHub.com (no data residency)GEI (ELM only targets GHE.com)
Move GHE.com → GitHub.com with official toolsGitHub Expert Services
Push a repo over GEI’s limits through GEI as isPush Git history only, Expert Services, or ELM from GHES

GHES → GHE.com: ELM vs GEI 📖 Docs

You can use both in the same migration. Pick per repo.

ELMGEI
⏱️ DowntimeCutover only (minutes)Repo frozen while it migrates
🎯 Best forLarge monorepos, critical repos that can’t stopTypical repos that can take a short freeze
🔀 Concurrency10 per GHES instance, 20 per targetHigher than ELM
🗂️ Git LFSMigratedNot migrated (push afterwards)
🧩 GHES versionSupported 3.17+ patches3.4.1+
💾 Staging storageNot neededBlob storage (GHES 3.8+)
🌐 TargetGHE.com onlyGitHub.com / GHE.com

⚠️ Avoid force pushes during the migration (ELM can’t reconcile the rewritten history). Public repos can’t exist on GHE.com, so make them private or internal first.

Switching EMU type: step by step 📖 Docs

Non-EMU → EMU and EMU → non-EMU follow the same flow.

  1. 🏢 Create a new enterprise (a trial works). An existing enterprise can’t be converted
  2. 🔐 Prepare identities: for EMU, SAML / OIDC and SCIM from the IdP; for non-EMU, each user’s personal account
  3. 🏷️ Decide org names: org names are unique across github.com. Use a new name on the target, or rename the source to free the name
  4. 🧪 Dry run, then production: test GEI migrate-org, then run production with work frozen. Add “Repository migrations” to the ruleset bypass list
  5. 👤 Bring users back: reclaim mannequins and sync team members. Users recreate PATs / SSH keys
  6. 💳 Switch billing: once migrated, work with GitHub Sales to retire the old enterprise
Slides 日本語