How-To Guide · Repository Migration
GitLab ships a built-in GitHub importer that brings across the repository, issues, pull requests as merge requests, wiki, milestones and labels. It works well, but it has real limitations that are much cheaper to discover before a cutover than after one — particularly around user attribution and comment history. This guide covers what actually transfers, what quietly does not, the two authentication routes and why the easier one is the one GitLab advises against, and how to verify a migration properly before you tell a team to stop pushing to GitHub.
The GitHub importer brings the repository description, the complete git history including branches and tags, issues, pull requests converted to merge requests, wiki pages, milestones and labels. That covers the substance of most repositories. What it does not bring is repository configuration — webhooks, deploy keys, branch protection, environments and secrets — or GitHub Actions workflows, all of which are rebuilt manually on the GitLab side.
Possibly, and this is the limitation worth testing before committing. GitLab documents that issue and pull request events — opened, closed, renamed, labelled, unlabelled — are not imported by default, and that comments may be skipped. Import one busy repository first and inspect its most-discussed issue and pull request specifically. If context matters to your team, keep the GitHub organisation archived and read-only rather than deleting it.
Because a PAT-based import cannot reliably associate imported activity with matching GitLab users. Issues and pull requests end up attributed incorrectly, and when you import into a personal namespace all contributions are assigned to a single non-functional account called Import User which cannot be reassigned afterwards. The GitHub integration route handles user mapping properly. Given the attribution damage is permanent, the extra setup is worth it.
No — they are rewritten. The two systems express similar concepts in incompatible syntax, so each workflow becomes a hand-written `.gitlab-ci.yml`. The mapping is straightforward once you have done one: Actions jobs to GitLab jobs, `runs-on` to an `image` plus runner tags, steps to `script` lines, repository secrets to masked CI/CD variables. Budget real time for this per repository, and run both pipelines in parallel before you trust the new one.
The import itself is minutes to a couple of hours per repository depending on size and history. The project around it is what takes time: inventorying repositories, rebuilding CI, recreating webhooks and branch protection, updating remotes across developer machines and deployment scripts, and verifying. A handful of repositories is comfortably a day or two. A large organisation with dozens of active repositories and complex CI is a multi-week project run in batches.
Yes — repository migration is one of the projects we run for Indian teams moving to GitLab, alongside the licensing. That covers inventory and batching, running imports with correct user mapping, rebuilding CI/CD as `.gitlab-ci.yml`, recreating branch protection and webhooks, verification, and cutover coordination so the freeze window is short. WhatsApp +91 98119 98370 with your repository count and CI complexity for a scoped quote in INR with GST invoice.