Migrate from Gitea to GitLab

Move Gitea repositories and issues into self-managed GitLab with the documented Gitea importer, and plan the work around CI/CD, users and cutover.

On this page

Migrate from Gitea to GitLab when your team outgrows a lightweight Git server

Repositories and issues can move from Gitea to self-managed GitLab with the Gitea importer that GitLab documents among its import sources, but pipelines, users, permissions and integrations are separate projects with their own inventories and cutover steps. A team that moves only the code and issues will still have to rebuild its CI/CD, reconcile who owns which account and reapply access rules. Plan those workstreams before you schedule the import. The usual trigger is a need for GitLab CI/CD, security scanning or compliance features that a lightweight Git server does not provide, so the first decision is which GitLab tier those features require. GitLab Free costs 0 US dollars, Premium costs 29 US dollars per user per month billed annually according to the GitLab pricing page, and Ultimate is custom priced. Premium covers advanced CI/CD and priority support, while application security testing, software supply chain security, vulnerability management and compliance features sit in Ultimate. Confirm the tier against the features you named before you count seats.

Effort depends on three variables: the number of repositories and the size of their history, how much of your Gitea CI work is Gitea Actions that must be rewritten as GitLab CI/CD, and how identities map from Gitea accounts to your corporate directory. Repository and issue volume drives import time, and placeholder user mapping becomes the slow part when many contributors have left the organization. We do not give a duration without a scoped inventory of repositories, workflows, packages, webhooks, runners and accounts, and that inventory is the first deliverable we would ask for in any planning phase. Note the Gitea version you run, because importer behavior and API details differ across releases. Gitea v28.1.0 was the current release in the reference we hold, so use it only as a point of comparison when you check your own version with the Gitea documentation.

What maps from Gitea to GitLab and what does not

This table compares the main Gitea objects and features against their GitLab counterparts and notes where the importer carries data across and where a separate move is needed. Read the migration notes column before scoping, because the rows marked for rework or separate handling usually drive the effort.

Gitea itemGitLab equivalentMigration note
Repositories and branchesProjects and branchesThe Gitea importer brings Git history, branches and tags. Confirm default branch and protected branch rules after import, since these are set separately.
TagsTagsTags come across with the Git history. Check that release tags point to the same commits as before.
Issues and labelsIssues and labelsIssues, comments and labels are imported. Confirm which label colors and scoped labels need recreating by hand.
MilestonesMilestonesConfirm milestone dates and issue assignments in a test import, since mapping depends on the importer version you run.
Pull requestsMerge requestsGitea pull requests become merge requests. Review open PRs before cutover, because approvals and review threads may not carry over in the same form.
WikiProject wikiWiki content is a separate Git repository in each system. Plan to clone and push it separately and verify links.
Organizations and teamsGroups, subgroups and membersRecreate the group structure and roles in GitLab first, then import projects into it. Team membership is not a one-to-one mapping.
Gitea Actions workflowsGitLab CI/CD pipelines in .gitlab-ci.ymlWorkflows are not imported. Rewrite them as GitLab CI/CD pipelines, and move runners, secrets and environment variables as separate tasks.
Package registriesGitLab package registry or an external registryPackages are not moved by the repository import. Export or republish artifacts separately and update client configuration.
Enterprise audit logging, IP allowlisting, SAML and mandatory 2FAGitLab Ultimate or Premium features, depending on the featureNo direct carry-over. Map each control to the GitLab tier that provides it and confirm availability on your self-managed edition before design sign-off.

Documented import paths for Gitea data

Gitea data reaches GitLab through a few documented routes, and each one carries a different slice of your history. The Gitea importer handles repositories and issues, direct transfer and file export cover moves between GitLab instances, and URL or manifest imports catch what the importer leaves behind. Plan the migration around which route carries which data.

Gitea importer for repositories and issues

The GitLab import documentation lists Gitea as a supported source, so repositories and issues can be brought in through the importer rather than rebuilt by hand. Treat the importer as the starting point for the project inventory, not the final word on what moves. Before the first run, ask which fields the importer carries for your target GitLab version, including labels, milestones, comments and attachments, and test on a copy of one representative project. Record what did not come across so it can be handled separately.

Direct transfer between GitLab instances

Direct transfer and file export are the documented ways to move groups and projects between GitLab instances. They become relevant when Gitea data is first imported into a staging instance and then moved to the production instance, or when a team consolidates several instances. Confirm that the admin setting for direct transfer is enabled on both sides, and check how user mapping behaves for contributors who have no account on the destination.

File export for controlled handoffs

File export produces a packaged copy of a project that can be moved on approved media or through a controlled transfer path. This suits air-gapped or tightly controlled networks where a direct connection between systems is not allowed. Ask who approves the export, where the archive is stored while it is in transit, and how its integrity is checked on arrival. Confirm the file contents and size limits for your version before planning the transfer window.

Git import by URL or manifest

Repositories the Gitea importer does not reach can still move as plain Git content, by importing from a Git URL or from a manifest listing several repositories. This route carries commit history and branches but not Gitea-specific objects such as issues, pull request discussions or wiki content. Use it for archived repositories, mirrors or forks that need to exist in GitLab, and keep a list of what was moved by this path so reviewers know which projects lack issue history.

Gitea Actions need a manual rewrite

Gitea Actions workflows are not converted automatically into GitLab CI/CD pipelines. Gitea describes Actions as designed to be compatible with GitHub Actions, but that compatibility does not make the workflow files portable to GitLab. Inventory every workflow, its triggers, secrets, runner labels and artifacts, then rewrite each one as a .gitlab-ci.yml pipeline and test it on a GitLab runner before cutover.

Confirm the mapping before cutover

Imported contributors appear as placeholder users until someone claims them, so authorship in migrated issues depends on how mapping is handled. Ask who will reassign placeholders, whether contributors will accept their mappings, and how many accounts the team expects to map. Run one test project end to end, including user mapping, before scheduling the production import, and record the outcome so the cutover checklist reflects what actually happened.

How the Gitea to GitLab cutover runs in phases

The sequence moves Gitea repositories, users, issues, workflows and packages into a self-managed GitLab in controlled stages, so each team validates reviews and pipelines before Gitea goes read-only. It ends with a documented, archived Gitea and a GitLab instance that holds the system of record.

  1. Prepare the GitLab instance before any import

    Choose an install method that fits your infrastructure, such as the Linux package, the Helm chart, the GitLab Operator, Docker or source. The Linux package bundles PostgreSQL, Redis and Sidekiq and is described as the most mature, scalable method. Before go-live, configure backups, confirm the backup and restore procedure on a non-production instance, and plan your upgrade path. GitLab requires upgrades to pass through required upgrade stops, which currently fall at x.2, x.5, x.8 and x.11 releases, so the target version should be chosen against that schedule. Done means a tested restore and a written upgrade plan signed off by the platform owner.

  2. Inventory repositories, users, issues, workflows and packages

    Export a full list of Gitea organizations, repositories, branches, tags, users, teams, issues, labels, milestones and wiki pages. Record which Gitea Actions workflows run in each repository and which package registries (npm, PyPI, Maven, container images, Helm charts) are in use, since each needs its own destination decision. Identify repositories with large binary history or LFS objects and decide how they will move. Flag Gitea Actions workflows for separate rewriting into GitLab CI/CD. Done means a signed inventory where every item has an owner and a target: import, rebuild, archive or retire.

  3. Pilot the import with a representative group

    Import one group that covers typical complexity: a few repositories, active issues, a mix of users and at least one pipeline. Use the Gitea importer from the GitLab import documentation and record what came across, what did not, and how users were mapped to placeholder accounts. Check commit authorship, merge history, issue labels and attachments against the source. Run a pipeline on the imported repository with a GitLab Runner to confirm the runner setup works. Done means a written pilot report listing gaps, each with a decision about how to handle it in the full import.

  4. Run the full import and assign contributor mappings

    Import the remaining groups in batches using the approach validated in the pilot, keeping each batch small enough to verify. Assign contributor mappings so that imported activity links to the correct GitLab users once they sign in. Rebuild required Gitea Actions workflows as GitLab CI/CD pipelines, and configure runners, CI/CD variables and protected branches to match the controls the teams used before. Done means every batch has a reconciliation record showing repository counts, issue counts and mapping status.

  5. Run a parallel period where both systems hold current data

    Keep Gitea writable while teams work in GitLab and validate code reviews, merge requests, pipelines and package publishing against the same work. Re-sync changed repositories and issues on a schedule agreed in advance, and log every discrepancy with an owner. Confirm that access groups, branch protection and approval rules behave as intended in GitLab. The parallel run is complete when teams sign off that reviews and pipelines work for their daily tasks and the discrepancy log is empty or accepted.

  6. Cut over with a write freeze on Gitea

    Announce the cutover window and place Gitea into a write freeze so no new pushes, issues or comments land after the final sync. Run the last incremental import, verify commit counts and reference integrity against the frozen source, and update remote URLs, CI integrations, webhooks and package consumers to point at GitLab. Switch teams to GitLab as the only place for new work. Done means the final reconciliation has been signed by the repository owners and the GitLab instance is recorded as the system of record.

  7. Retain read-only Gitea archives, then decommission

    Keep Gitea in read-only mode for a retention period set by your records policy, confirm with compliance owners what evidence and history must remain accessible, and export archives where required. Remove Gitea webhooks, runners, tokens and service accounts, then shut down the service and its database. Record the decommissioning steps and the location of the archives. Done means Gitea is offline, archives are indexed and access to them is documented for auditors and future readers.

What drives the cost and duration of the move

This table lists the factors that change how much work the Gitea to GitLab move takes and what each one costs. Read each row for whether the cost is one-time or recurs, and use the quote question to make sure a partner prices the same thing you have counted.

DriverWhy it changes cost or effortOne-time or recurring, and what to ask for
Repository count and history sizeEach repository is imported, checked and re-linked. Large histories and LFS objects take longer to transfer and verify.One-time. Ask the partner to list repositories by size, how LFS objects will be handled, and what verification is included.
Issues, pull requests and attachmentsThe Gitea importer brings issues and related content across, but volume and attachment size affect transfer time and spot checks.One-time. Ask for an issue count per project and whether attachments are in scope or must be exported separately.
Gitea Actions workflowsGitea Actions is designed to be compatible with GitHub Actions, but each workflow still has to be reviewed and rewritten as GitLab CI/CD pipelines.One-time. Ask for the workflow count, the runners they target, and which secrets and variables each one uses.
Package registries in useGitea supports more than 20 registry types. Each registry in use needs a target in GitLab and its own client configuration change.One-time, with some recurring checks. Ask which registry types are used and how package history will be handled.
User and placeholder volumeImported contributions are attached to placeholder users until someone claims them. Large user lists take more mapping and follow-up.One-time. Ask how placeholder users will be reassigned and who completes acceptance for each contributor.
Identity integrationConnecting GitLab to your identity provider (SAML, LDAP, OAuth 2.0, SCIM) adds configuration, group mapping and testing.One-time for setup, recurring for group and provisioning changes. Ask which provider is used and whether SCIM is required.
GitLab edition choicePremium and Ultimate add features such as advanced CI/CD, security scanning and compliance tooling. Each edition has a different licensing cost.Recurring per user per month for paid tiers. Ask for the edition mapped to your required features and the quote basis for Ultimate.
Runner fleet designExisting Gitea Actions runners may not match GitLab Runner executors. New runners need hosts, isolation, and autoscaling configuration.One-time for build, recurring for capacity and patching. Ask which executors are planned and who operates the fleet.
Integrations to reconnectChat, issue trackers, secrets managers, Kubernetes clusters and deployment tools each need re-pointing and testing after cutover.One-time per integration. Ask for a list of integrations, their owners and the test steps for each.

What usually goes wrong in Gitea to GitLab moves

Most Gitea to GitLab problems come from the people, access and automation around the code rather than the repositories themselves. The cards below cover the risks that show up most often in planning and cutover, with a prevention step for each. Check them against your own user list, pipeline inventory and integration map before the import starts.

Contributions left on placeholder users

Imported issues, comments and merge requests are first attributed to placeholder users until each Gitea account is matched to a GitLab user. If the match is skipped, history reads as if nobody wrote it, and audit trails for reviews become hard to defend. Before the import, export the Gitea user list, decide how each account maps to a GitLab identity, and confirm with the team who will accept the reassigned contributions. Check the placeholder limit on your instance for a large migration.

Pipelines broken by the rewrite

Gitea Actions is designed to be compatible with GitHub Actions, but GitLab CI/CD uses its own pipeline syntax, runners and variables. Pipelines often fail after cutover because no runner matches the job tags, or because CI/CD variables and protected secrets were never recreated. Inventory every workflow file, list the runners and variables each job needs, and run the rewritten pipeline on a non-production branch before retiring the old one.

Permissions drifting from Gitea teams

Gitea organizations and teams do not map one to one onto GitLab groups, subgroups and project roles. Access that looked correct in Gitea can end up broader or narrower after import, and branch protection rules are not always carried over. Write down the current team-to-repository access matrix, decide the target GitLab group structure, and compare effective access for a sample of sensitive repositories after the import.

Webhooks and bots still pointing at Gitea

Chat notifications, deployment triggers, dependency bots and build servers often call Gitea endpoints directly. After cutover, they keep working on stale events, go silent, or fail without a clear error. Search your secrets stores and automation for Gitea URLs and tokens, then list each consumer with its owner. Replace hooks and bot configurations with GitLab equivalents and disable the old ones only after the new ones are confirmed.

Writes split across both systems

When developers keep pushing to Gitea during a parallel run, commits, branches and issues diverge, and the team ends up merging two histories by hand. Set a freeze date for each repository, make Gitea read-only at that point, and tell teams which system is the source of truth for every project. Re-run the final sync after the freeze, then verify commit counts and default branches before the old repository is archived.

Questions teams ask before moving from Gitea to GitLab

What does a Gitea to GitLab migration cost?

No figure is given without a written scope, because the cost depends on how many repositories, issues and users are moving, how much CI/CD must be rebuilt, and which GitLab edition the team selects. The main cost components are the people who plan and run the import, the people who rebuild pipelines and runners, and the infrastructure for the new self-managed instance. The import itself is a one-time cost, while the GitLab subscription, infrastructure and runner capacity recur. Ask any provider for a quote that separates one-time migration work from recurring support, and that lists what is excluded, such as Gitea Actions rewrites or access model changes.

How long does a migration from Gitea to GitLab take?

The timeline is set by inventory size, the number of Gitea Actions workflows to rebuild, how many users need identity setup, and how long the cutover window can be. Repository and issue import is usually the shortest part. Pipeline rewrites, runner provisioning, access testing and a parallel run period usually take longer. Confirm the duration with your provider against your own inventory, and plan a pilot group of projects first so that the team can measure real effort before scheduling the rest.

What must our team provide before a migration starts?

Your team needs to provide a complete inventory of repositories, issues, packages, webhooks and CI/CD workflows, along with named owners for each group or project. Approvers must be identified for the cutover decision and for any change to access rules. The team should also supply test pipelines that represent real builds and deployments, plus the accounts and secrets needed to verify them. Without these inputs, scope cannot be fixed in writing, and the migration will stall at ownership questions rather than technical ones.

Can our internal team migrate from Gitea to GitLab alone?

An internal team with Linux, database and Git administration experience can usually handle the import of simple repositories and issues. Teams most often need help with the GitLab installation design, backup and restore procedures, runner fleet setup, identity integration, and the rewrite of CI/CD pipelines. External help is also useful for the first upgrade plan, because GitLab requires upgrade stops. Decide early which parts your team will own after handover, and ask any partner to document those parts so that operations continue without them.

Do Gitea Actions workflows move to GitLab automatically?

No. The Gitea importer brings over repositories and issues, but CI/CD workflows must be rewritten as GitLab CI/CD pipelines. Gitea Actions is designed to be compatible with GitHub Actions, so some workflow logic may translate with review, but jobs, runners, secrets, variables and environments all need to be mapped and tested. Plan for the new pipelines to run in parallel with the old ones until builds and deployments produce matching results.

Which GitLab tier do we need for security scanning or compliance features?

GitLab Free costs 0 dollars and GitLab Premium costs 29 US dollars per user per month billed annually, according to the GitLab pricing page. The pricing page lists advanced CI/CD and priority support for Premium, and application security testing, software supply chain security, vulnerability management and compliance features for Ultimate, which is custom priced. All three tiers are available for self-managed installations. Confirm the exact feature set for your version on the pricing page before deciding, and ask your provider which scanners your environment can run offline if you operate in an isolated network.

Should we keep Gitea running during the migration?

Usually yes, for a defined period. Keeping the source instance read-only after cutover gives teams a fallback and a reference for issue history and pipeline behavior. Decide how long it stays available, who may write to it, and when it is decommissioned, and record that decision in the cutover plan. Confirm the retention requirements with your compliance owner, since audit evidence may need to come from the old system.

What changes for developers and administrators after cutover

Developers feel the cutover first, mostly through their local clones. Each repository needs its remote pointed at the new self-managed GitLab project, so the team should decide whether to rewrite remotes in bulk or have each developer update them as they pick up work. Pull requests from Gitea become merge requests in GitLab, and the review habits carry over, but approval rules, draft status and discussion threads sit in different places, so teams should walk through one real review before the first live cutover. CI/CD is the bigger change. Gitea Actions workflows do not run unchanged, and the pipeline definition moves into .gitlab-ci.yml, with jobs executing on GitLab Runners that your team must register and keep available. Confirm early which runner types you will operate and who owns the rewritten pipelines.

Administrators take on responsibilities that a lightweight Gitea server often hides. Upgrades must follow the required upgrade stops published in the GitLab upgrade paths documentation, so a version that is too far behind may need intermediate steps before it can move forward. Backups need to cover the database, Git data and the secrets file, and a restore should be rehearsed rather than assumed. Runner versions should match the GitLab major and minor version, which means runner upgrades belong in the same change calendar as GitLab upgrades. Authentication also shifts ownership: if you plan to use SAML, LDAP, OmniAuth or other providers, configure them in GitLab before users arrive, and confirm which accounts stay local for break-glass access. Assign these duties to named owners before the migration window opens.

How DeployOpen scopes and delivers the Gitea to GitLab migration

DeployOpen plans, implements, tests, documents and supports self-hosted open-source platforms inside your own infrastructure, including cloud accounts, data centers and air-gapped networks. For this migration, we start from a written scope that names the Gitea repositories, issues and pipelines to move, the GitLab instance that receives them, and the checks that show the move worked.

How we scope

  • We inventory Gitea repositories, issues, users and Gitea Actions workflows to decide what the importer moves and what needs manual work.
  • We confirm your Gitea version, database and whether the GitLab target is Free, Premium or Ultimate before any import runs.
  • Fixed-scope engagements are agreed in writing, so deliverables, timelines and acceptance checks are known before work begins.

How we build

  • We stand up or verify the target GitLab instance and its upgrade stop position, then rehearse the import on a copy of a sample project set.
  • We map Gitea users to GitLab accounts and document how placeholder users are reassigned after the import completes.
  • We rebuild CI/CD pipelines as GitLab CI/CD jobs and register runners, and we test each pipeline against the migrated repositories.

How we hand over

  • You receive a runbook covering the cutover sequence, rollback steps, the import log review and the final repository and issue reconciliation.
  • We document which Gitea features did not move, such as certain issue metadata or Gitea-specific settings, so your teams know what to recreate.
  • Operating notes cover runner maintenance, backup scheduling for the new instance and the ownership of each repository after cutover.

How we support

  • Post-cutover support can be arranged as a retainer for fixes, upgrades and runner changes once your teams operate GitLab day to day.
  • We agree the support scope, response expectations and upgrade planning in writing, so the arrangement matches your operating model.
  • Ask any provider to confirm which GitLab and Gitea versions they will test against, and how they will verify the imported data.

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.