Join our Newsletter — 33% off our NHI Course
Home› Guides› Source control platform migration playbook: moving platforms without…
Guide Software & AI Supply Chain

Source control platform migration playbook: moving platforms without losing control

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 11 November 2026 12 min read
On this page

Git history moves between platforms with one command, but almost everything that protects the code does not: branch protection, required reviews, code owners, deploy keys, app installations, webhooks and access groups live in the platform, not in the repository, and have to be rebuilt deliberately. Organisations migrate source control platforms when a self-hosted server reaches end of support, when they move to a hosted service or back on premises, after mergers, and when consolidating several platforms into one. This playbook covers the migration itself: what is in Git and what is not, how to move history completely and prove it, how to deal with secrets already in history, how to rebuild the controls and non-human identities around the code, and how to retire the old platform. It is vendor-neutral and based on the Git documentation, NIST SP 800-218 (SSDF), NIST SP 800-204D, the CISA and NSA guidance on defending CI/CD environments and the OpenSSF Scorecard checks. Ongoing repository hardening is in the Git Repository Security Guide.

Key takeaways

  • Git is the easy part. A mirror clone moves all refs; the controls, identities and integrations around the repository are platform metadata that must be rebuilt.
  • Secrets in history migrate too. Every credential ever committed arrives on the new platform; scan before the move and rotate what you find, because history rewriting does not make a leaked secret safe.
  • Rebuild protections before opening write access. The window between import and protection is when the new platform has code without review rules.
  • Machine access is the long tail. Deploy keys, app installations, CI tokens, webhooks and automation accounts outnumber people; inventory and reissue them, do not copy them.
  • One writable home per repository. During the overlap, make the old repository read-only as soon as the new one accepts pushes, or the two will diverge.

What is in Git and what is not

ObjectWhere it livesMigration approachWatch for
Commits, branches, tags, notesGitMirror clone and push all refsPlatform-specific hidden refs (for example review refs) that a mirror may or may not include
Large file storage objectsSeparate object store referenced by pointers in GitFetch all objects for all refs and push them to the target's storePointers arrive but the files do not; builds fail later
Commit and tag signaturesGit objectsPreserved by the mirror; re-register signing keys on the target for verification displaySignatures reported as unverified because keys or identities were not mapped
Pull or merge requests, reviews and commentsPlatformMigration tooling or export; at minimum archiveReview evidence needed for audit lost with the old platform
Branch protection, required reviews, code owners rulesPlatform (code owners file is in Git; enforcement is not)Recreate as configuration and test that it blocksRules that existed per repository with no central record
Users, teams and permissionsPlatform and identity providerMap groups from the identity provider; rebuild by intentPersonal accounts, outside collaborators and administrator rights copied across unchanged
Deploy keys, access tokens, app installationsPlatformInventory and reissue on the targetOld keys and tokens still valid on the old platform after cutover
Webhooks and integrationsPlatformRecreate with a shared secret; remove from the old platformWebhook payloads still sent to retired endpoints
CI configuration and stored CI secretsGit (definitions) and platform (secrets)See the CI/CD server migration playbookPipelines that run on import with no protections yet
Audit logsPlatformExport and archive for the retention periodEvidence of past access lost

Moving history completely and proving it

The Git documentation describes git clone --mirror as setting up a mirror that maps all refs, including remote-tracking branches and notes, not just local branches. For repositories using large file storage, the Git LFS documentation describes git lfs fetch --all as downloading all objects referenced by any commit reachable from the given refs, and says this is primarily for backup and migration purposes. Use both.

  1. Mirror clone each repository from the source to a controlled migration host.
  2. Fetch all large file objects for every ref if the repository uses large file storage.
  3. Check integrity: run git fsck, which verifies the connectivity and validity of the objects in the database, on the mirror before pushing.
  4. Push all refs and large file objects to the target.
  5. Prove equality: compare the list of refs and the commit each points to in source and target. Matching commit IDs mean matching history, because Git identifies commits by the hash of their content.
  6. Check signatures: spot-check signed commits and tags with git verify-commit and git verify-tag on a clone of the target.

Keep the mirror clones as an archive, protected like the source, until the old platform is decommissioned. NIST SP 800-218 task PS.1.1 asks that all forms of code be stored on the principle of least privilege; the migration host and its clones are in scope.

Secrets already in history

A migration copies every secret ever committed, in every branch and tag. In the Uber 2016 breach, an AWS key in a private repository opened the way to data on 57 million people; private does not mean safe.

  • Scan full history before migrating: NIST SP 800-204D recommends scanning repositories for secrets even before they are populated, since exposed credentials may already be leaked. Scan all refs of each mirror, not only the default branch. See the Git Secret Scanning Guide.
  • Rotate first: revoke and replace every valid secret found at the system it grants access to. That is the fix; anything else is clean-up.
  • Rewrite history only by decision: rewriting changes every later commit ID, breaks signatures, open reviews and references in other systems. Do it when policy requires removing the data, after rotation, and before the push to the target, so the target never holds it.
  • Turn on push protection in the target before developers start pushing. NIST SP 800-204D lists push protection that scans commits for keys and tokens as a requirement (COMMIT-REQ-1).

Secrets found in Git are a common breach path; see the Internet Archive breach, where an exposed source control token was part of the chain.

Rebuilding controls around the code

The OpenSSF Scorecard checks give a useful list of platform settings that do not travel with Git: Branch-Protection, Code-Review, Token-Permissions, Dangerous-Workflow and Webhooks (whether webhooks authenticate request origins with a secret). Recreate each, then confirm with the same checks on the target.

ControlTarget settingSource guidance
Protected default and release branchesNo direct pushes, no force pushes, no deletion; status checks requiredOpenSSF Scorecard Branch-Protection
Two-person reviewAt least one approving review from someone other than the author; approvals reset on new commitsCISA and NSA two-person rule; NIST SP 800-204D
Code owners for sensitive pathsRequired review from owners of pipeline definitions, infrastructure code and security configurationNIST SP 800-204D treats SCM write access as high risk
Signed commitsRequired on protected branches where the organisation signsCISA and NSA recommend signing code and CI/CD configuration and verifying signatures
Fork and outside contributor buildsApproval required before CI runs for outside contributorsNIST SP 800-204D (strictest setting)
Default job token permissionsRead-only by defaultOpenSSF Scorecard Token-Permissions
WebhooksShared secret configured on every webhookOpenSSF Scorecard Webhooks
Single sign-on and MFAAll users through the identity provider; phishing-resistant MFA for administratorsCISA and NSA recommend MFA and federation for humans

Apply these at organisation level where the target allows, so new repositories inherit them. The GitHub Organisation Security Checklist shows the settings on one common platform.

Where identity fits

A source control platform holds more machine identities than most teams realise, and they are the ones that get copied without review.

IdentityTarget patternBefore cutover
Deploy keys (per repository SSH keys)New key pair per consumer, read-only unless write is justifiedList from the source; drop unused ones. See How to find unused GitHub deploy keys and SSH keys
Personal access tokens used by automationApp or service identity with scoped, expiring tokensFind automation running as people
Installed apps and OAuth integrationsReinstall only reviewed apps, scoped to named repositoriesSee How to audit GitHub Apps and OAuth apps in an organisation
Machine users and bot accountsReplace with app identities where possible; owner and expiry for eachSee How to audit GitHub outside collaborators and machine users
Migration identityRead on source, create and write on target, per waveTime-boxed; removed at sign-off

The platform's tokens are a prime target: the Gitloker campaign used malicious OAuth apps and stolen credentials to wipe repositories. A migration is the moment to cut that integration surface down. MITRE ATT&CK tracks collection from code repositories as T1213.003.

The phased playbook

  1. Inventory: repositories with owners and activity, large file usage, users and groups, outside collaborators, deploy keys, tokens, apps, webhooks, CI integrations, and every external system that clones from the old URLs (build servers, package builds, documentation sites, scripts).
  2. Design the target: organisation structure, groups mapped from the identity provider, organisation-wide protection rules, push protection, default token permissions and the app allow list.
  3. Scan and rotate: scan the full history of each mirror for secrets and rotate valid findings before the repository is pushed.
  4. Pilot: migrate one active repository with large files, signed commits and CI; confirm protections block a direct push and an unreviewed merge.
  5. Migrate in waves: archive-only and inactive repositories first, then active ones by team. For each repository: freeze the source branch for writes, mirror, verify, push, apply protections, then open the target for writes.
  6. Switch consumers: update remotes in CI, deployment and automation; reissue deploy keys and tokens; recreate webhooks with secrets.
  7. Make the source read-only: archive each migrated repository on the old platform and alert on any push or new token use.
  8. Decommission: export audit logs and review history, revoke every remaining key, token and app installation on the old platform, delete its accounts in the identity provider, then sanitise storage and backups following NIST SP 800-88.

Rollback: until the source is decommissioned, rollback for a repository means re-opening the source for writes after pushing back any commits made on the target (a mirror push in the other direction). Because both sides hold the same commit IDs, this is safe as long as only one side has been writable at a time. Small organisations can often migrate everything in one weekend with a write freeze; large estates need waves per team and a published mapping of old to new URLs.

Detection and measurement

Metric or signalWhy it mattersTarget (our recommendation)
Repositories with matching refs and commit IDs in source and targetCompleteness of history100% of migrated repositories
Active repositories meeting the protection baselineControls were rebuilt100% before open for writes
Valid secrets found in history and not yet rotatedExposure carried acrossZero at wave sign-off
Pushes, clones or token use on the old platform after read-onlyMissed consumers or misuseZero unexplained; alert on pushes
Machine identities on the target versus sourceIntegration surface reduced, not copiedFewer, each with owner and expiry
Large file pointer errors in buildsObjects not migratedZero

Send the audit logs of both platforms to the same place throughout. See the GitHub Audit Log Detection Guide for the kinds of events to watch on one platform.

Common failure patterns

  • Protections applied after import: repositories are open for writes for days before branch protection and review rules are set.
  • Secrets carried in history: credentials committed years ago arrive on a new platform, sometimes with wider visibility than before.
  • Large file objects left behind: pointer files migrate, the content does not, and the old platform cannot be retired.
  • Dual writes: both repositories accept pushes, histories diverge and a fix lands only on the old one.
  • Copied machine access: every deploy key, bot account and app is recreated without review, so the target inherits the old platform's sprawl.
  • Old platform kept alive: left running, unpatched and still holding valid tokens, "for reference".

Framework mapping

ActivityNIST SP 800-53 Rev 5NIST CSF 2.0Other
Protecting code on both platformsAC-6, CM-5PR.AA-05SSDF PS.1.1
Rebuilding branch protection and reviewSA-10, CM-3PR.PS-06OpenSSF Scorecard Branch-Protection, Code-Review
History integrity and signed commitsSI-7, CM-14PR.DS-01SSDF PS.2
Secrets in history and machine identitiesIA-5PR.AA-05ATT&CK T1552.001
Inventory of repositories and integrationsCM-8ID.AM-02
Audit logs and archivesAU-2, AU-11, CP-9DE.CM-09, PR.DS-11
Threats the migration must not reopenAC-6PR.AA-05ATT&CK T1213.003, T1195.002

Practitioner checklist

  • Inventory repositories, identities, integrations and external consumers of old URLs.
  • Mirror clone, fetch all large file objects and run git fsck before pushing.
  • Compare refs and commit IDs between source and target for every repository.
  • Scan full history for secrets and rotate valid findings before the push.
  • Apply protection rules and push protection before opening the target for writes.
  • Reissue deploy keys, tokens and app installations; never copy them.
  • Recreate webhooks with shared secrets and delete them from the old platform.
  • Keep exactly one writable home per repository during the overlap.
  • Archive review history and audit logs for the retention period.
  • Revoke everything on the old platform, then decommission and sanitise.

Standards and references

Related NHI Mgmt Group resources: Git Repository Security Guide · Git Secret Scanning Guide · GitHub Organisation Compromise Playbook · CI/CD server migration playbook · Artefact and container registry migration playbook

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 11 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org