What are the key challenges and strategies for migrating a large organization from GitLab, Bitbucket, or Azure DevOps to GitHub, and how do you handle CI/CD pipeline translation?
Quick Answer
Large-scale migration to GitHub requires a phased approach covering repository migration (with history), CI/CD pipeline translation (GitLab CI/Azure Pipelines to GitHub Actions), permissions mapping (groups to teams), and data migration (issues, PRs, wikis). GitHub's GitHub Enterprise Importer (GEI) handles repository and metadata migration, while CI/CD translation requires manual workflow rewriting with abstraction layers.
Detailed Answer
Migrating a 200-repository organization to GitHub is like relocating a hospital to a new building. You cannot move all departments simultaneously—patients would die. Instead, you move one department at a time, ensure the critical equipment works in the new location, maintain emergency services throughout, and run both facilities in parallel during transition. The migration is not just about moving boxes (code); it is about translating procedures (CI/CD), transferring records (issues and PRs), and retraining staff (developer workflows).
The migration architecture has four major workstreams. Repository migration handles moving git history, branches, tags, LFS objects, and submodule references. GitHub Enterprise Importer (GEI) is the official tool that migrates repositories from GitLab, Bitbucket Server, Azure DevOps, and other GitHub instances. GEI preserves commit history, branches, and tags, and can migrate pull requests, issues, and some CI/CD metadata. For repositories using Git LFS, objects must be migrated separately using 'git lfs fetch --all' followed by 'git lfs push --all' to the new remote. Submodule references need URL updates across all repositories that reference migrated repos.
CI/CD pipeline translation is the most labor-intensive workstream. GitLab CI uses .gitlab-ci.yml with stages, jobs, and GitLab-specific features like includes, extends, and environment-scoped variables. Azure Pipelines uses azure-pipelines.yml with stages, jobs, and tasks from the Azure marketplace. Neither maps 1:1 to GitHub Actions. The strategy is to create an abstraction layer: identify common pipeline patterns (build, test, scan, deploy), implement them as reusable GitHub Actions workflows, and migrate repositories in groups that share pipeline patterns. For example, all Node.js microservices at acme-corp (payments-api, user-auth-service, notification-service) share a common build-test-deploy pipeline in GitLab CI, which becomes a single reusable workflow in GitHub Actions called by each service.
Permissions and access control migration maps GitLab groups and Bitbucket projects to GitHub organizations and teams. GitLab's five permission levels (Guest, Reporter, Developer, Maintainer, Owner) map to GitHub's roles (Read, Triage, Write, Maintain, Admin). SAML SSO and SCIM provisioning must be configured before user migration to maintain identity federation. Repository visibility (public, internal, private) and branch protection rules need manual reconfiguration, as these settings do not transfer via GEI. Protected branches with approval requirements should be converted to GitHub rulesets for centralized management post-migration.
The most critical risk is the parallel operation period. During migration, some teams are on GitHub while others are still on GitLab, and cross-team dependencies create integration challenges. Mitigate this by migrating in dependency order: shared libraries first, then services that depend on them. Set up bidirectional mirroring using tools like 'git-mirror' or CI jobs that push to both remotes during the transition period. Another major gotcha is CI/CD secret migration—secrets exist only as encrypted values in source platforms and cannot be extracted programmatically. You must re-create every secret in GitHub, which is a manual and error-prone process. Audit all secrets before migration to eliminate stale credentials. Finally, webhook integrations with external services (Jira, Slack, Datadog) need reconfiguration for GitHub's webhook format, which differs from GitLab's and Azure DevOps's payload schemas.