Azure DevOps → GitLab
Move repositories, refs, pull requests, issues, users, LFS, pipelines, packages, permissions, webhooks, and audit evidence from Azure DevOps into GitLab with an explicit exception ledger and evidence-based cutover.
Should you make this move?
Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.
Azure DevOps
- Repos, boards, pipelines, artifacts, and enterprise controls are tightly integrated
- Repository-centered workflows keep code, review, and automation close together
- The interface and administration model can feel heavy outside Microsoft-centric organizations
- Advanced governance and automation can become configuration-heavy
GitLab
- A comprehensive DevSecOps platform offers deep CI/CD and self-hosting options
- Repository-centered workflows keep code, review, and automation close together
- Breadth, upgrades, and administration can be heavy for smaller teams
- Advanced governance and automation can become configuration-heavy
GitLab: A comprehensive DevSecOps platform offers deep CI/CD and self-hosting options. This removes a major source-side concern: The interface and administration model can feel heavy outside Microsoft-centric organizations.
What you lose: Repos, boards, pipelines, artifacts, and enterprise controls are tightly integrated. What you inherit: Breadth, upgrades, and administration can be heavy for smaller teams.
Know the shape of the move.
This timeline assumes
- Up to 100 repositories, 500 GB of Git data, and 250 users
- Administrators control both platforms, identity mapping, DNS, registries, and every repository integration.
- A representative repository set is migrated into an isolated destination organization first.
- The source remains read-only until developers and automation pass one complete release cycle.
- The migration team records evidence for every blocking verification check.
What survives the move.
“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.
| Item | Outcome | Impact | What happens | Mitigation |
|---|---|---|---|---|
| Git repositories, branches, tags, commits, and selected work metadata | partial | critical | Core git repositories, branches, tags, commits, and selected work metadata can move, but Azure DevOps and GitLab use different models, limits, identifiers, and import behavior. | Pilot every feature class, preserve source IDs, and reconcile accepted, transformed, rejected, and excluded items. |
| Boards, Pipelines, Artifacts, permissions, service connections, and post-snapshot changes | manual | critical | Azure DevOps services outside Git require separate import, rebuild, integration, archive, or retirement decisions. | Inventory every active dependency, approve its destination disposition, and test the replacement before source writes stop. |
| Git repositories and commit history | clean | critical | Git source, branches, tags, and commits can move through supported importers or mirror pushes. | Compare refs, commit graphs, default branches, submodules, signatures, and shallow state. |
| Pull or merge requests | partial | critical | Metadata migration depends on the selected importer and supported source version. | Pilot open, closed, merged, draft, forked, and large requests. |
| Issues, comments, and discussions | partial | high | Coverage, formatting, attribution, timestamps, and cross-links vary by migration path. | Preserve source IDs and URLs and reconcile representative conversations. |
| Users and contribution attribution | partial | critical | Email and username differences can create placeholders or migration identities. | Freeze an identity map and reclaim or annotate unmapped activity. |
| Git LFS and large binaries | partial | critical | Git history can move while LFS objects, package blobs, and releases require separate transfer. | Inventory object counts and compare hashes after migration. |
| Branches, tags, and protections | partial | critical | Refs move more easily than approval, push, merge, and signing policies. | Recreate rules before developers receive write access. |
| CI/CD pipelines and secrets | manual | critical | Pipeline syntax, runners, caches, artifacts, environments, and secret stores differ. | Translate and rehearse every active build and release workflow. |
| Packages, containers, and releases | partial | high | Registries and release assets do not necessarily follow repository data. | Copy immutable artifacts and update package coordinates and credentials. |
| Wikis, snippets, projects, and planning | partial | high | Collaboration products have different models and importer coverage. | Archive history and migrate only active shared knowledge and work. |
| Organizations, groups, teams, and permissions | manual | critical | Account hierarchy and inherited access never map safely by assumption. | Design and test least-privilege destination access first. |
Where each thing goes.
| Source | Destination | Method | Notes |
|---|---|---|---|
| Azure DevOps repository | GitLab repository | automatic | Preserve stable source URL and default branch. |
| Git branch and tag | Git branch and tag | automatic | Compare all refs after import. |
| Pull or merge request | Destination pull or merge request | transform | Depends on selected metadata importer. |
| Issue and comment | Destination issue and comment | transform | Preserve author, timestamp, ID, and URL. |
| Source user | Destination identity | manual | Freeze an identity map before migration. |
| Branch protection | Destination ruleset or branch restriction | manual | Rebuild before write access. |
| CI pipeline | Destination workflow | transform | Review every generated or translated step. |
| Package, release, or LFS object | Destination registry, release, or LFS object | transform | Copy binaries and compare hashes. |
| Group, team, or permission | Destination organization, team, and role | manual | Apply least privilege. |
Make the move recoverable.
Create the source-of-truth backup
Preserve Azure DevOps data, configuration, and operating evidence before any destination write.
- Inventory and export Azure DevOps repositories, metadata, users, permissions, pipelines, packages, releases, webhooks, and settings.
- Mirror every Git repository and fetch Git LFS objects.
- Record counts by repository, ref, pull request, issue, user, package, and integration.
- Hash archives and migration manifests.
Proof to capture: A signed manifest reconciles every scoped record class, runtime dependency, export file, count, and hash.
Repository and identity manifest
Preserve repository scope, Git refs, users, and metadata ownership.
- Inventory source values and exceptions.
- Define explicit destination mappings.
- Reject unmapped critical records.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
Workflow and integration conversion
Rebuild delivery and connected services safely.
- Normalize encoding, dates, identifiers, and blanks.
- Run a representative pilot.
- Reconcile accepted, rejected, and transformed rows.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
The things most likely to hurt.
These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.
A code-only move is mistaken for a metadata migration
Git refs exist while pull requests, issues, users, or settings are missing.
- Consequence
- Collaboration and control history disappears.
- Mitigation
- Choose and verify the required migration fidelity explicitly.
Stop if: Any required metadata class lacks a supported path.
Both platforms accept writes
Developers or bots push and update work in both systems.
- Consequence
- Repositories and release state diverge.
- Mitigation
- Freeze source writes and change remotes in one controlled window.
Stop if: Any unapproved source writer remains active.
Permissions or secrets are over-broad
Migrated users or automation receive more authority than intended.
- Consequence
- Code, packages, or production systems are exposed.
- Mitigation
- Apply least privilege before opening repositories.
Stop if: An unauthorized test identity can perform a protected action.
Do the work in this order.
- Days 1–3 · inventory
Inventory and decisions
6–12 hours active2–3 days elapsedOwner review waiting- Inventory Azure DevOps data, features, users, domains, and integrations.
- Approve scope, owners, mappings, and exclusions.
Depends on: Azure DevOps and GitLab administrator access
Stop / go checkpointExport?
Go when: Every critical item has an owner and disposition.
Stop when: Consent, billing, access, or system ownership is unclear.
- Days 3–5 · backup
Backup and reconcile
5–10 hours active1–3 days elapsedExport processing waiting- Create immutable exports and configuration evidence.
- Reconcile counts, totals, and hashes.
Depends on: Approved inventory
Stop / go checkpointTransform?
Go when: Source totals and export manifests agree.
Stop when: Any critical dataset or configuration is absent.
- Days 5–12 · pilot
Map and pilot
10–35 hours active3–8 days elapsedDestination processing and review waiting- Configure GitLab and transform representative data.
- Run a pilot containing normal records and every critical edge case.
Depends on: Verified backup
Stop / go checkpointScale?
Go when: Pilot mappings, behavior, access, and evidence pass.
Stop when: Any critical check fails or produces unexplained variance.
- Days 10–20 · cutover
Final delta and switch
5–25 hours active1–5 days elapsedDNS, import, or sync propagation waiting- Freeze production writes in Azure DevOps.
- Apply the final delta, switch ownership, and run blocking checks.
Depends on: Passed pilot and approved rollback
Stop / go checkpointOpen production?
Go when: Counts reconcile and one destination system owns production.
Stop when: A source writer remains active or a blocking check fails.
- Days 12–40 · observe
Observe and close
3–18 hours active3–10 days elapsedOperating-cycle evidence waiting- Monitor one complete operating cycle.
- Sign the verification report and close rollback only after stability.
Depends on: Verified cutover
Stop / go checkpointClose rollback?
Go when: No trigger occurs during the agreed observation period.
Stop when: Data, access, delivery, routing, or business results regress.
Cut over with a way back.
Cutover
Make GitLab the only production system without losing the final Azure DevOps delta.
- Freeze production writes and scheduled actions in Azure DevOps.
- Export, transform, and reconcile the final delta.
- Apply the approved delta to GitLab.
- Switch domains, forms, integrations, sending, or sync ownership as applicable.
- Run every blocking verification check and keep the source intact.
Proof to capture: GitLab owns production, totals reconcile, and every blocking check has durable evidence.
Rollback
Return production ownership to Azure DevOps without losing destination-era changes.
- Stop new writes and scheduled actions in GitLab.
- Restore the prior Azure DevOps routing, forms, integrations, sending, or sync ownership.
- Export the GitLab post-cutover delta.
- Review and apply safe destination-era changes to Azure DevOps.
- Run the same blocking checks against the restored source.
Proof to capture: Azure DevOps again owns production with current data and no duplicate destination action.
- Unexplained critical count or value variance
- Missing or exposed critical data
- Duplicate production action
- Failed access, routing, delivery, or integration check
- A critical feature has no safe destination replacement
Prove the migration worked.
Every blocking check must pass. Capture the evidence before cleanup begins.
| Pass | ID | Check | Method | Expected result | Evidence |
|---|---|---|---|---|---|
V-01Blocking | Repository and ref parity | Compare repositories, commits, branches, tags, default branches, submodules, and LFS. | Every scoped Git object is accounted for. | Git manifest. | |
V-02Blocking | Collaboration coverage | Compare pull requests, issues, comments, releases, wikis, and projects by source class. | Every required item is migrated or explicitly archived. | Metadata ledger. | |
V-03Blocking | Attribution mapping | Inspect active, inactive, bot, and external contributors. | Every required author has a destination or annotation. | Identity map. | |
V-04Blocking | Teams and repository rules | Test representative users and protected actions. | Least privilege and branch controls match policy. | Access report. | |
V-05Blocking | Build and release parity | Run representative workflows from identical commits. | Tests, artifacts, approvals, and deployments match. | Workflow evidence. | |
V-06Blocking | Packages, releases, and LFS | Compare counts, coordinates, sizes, and hashes. | Every required binary is present and retrievable. | Artifact manifest. | |
V-07Blocking | Connected services | Exercise each webhook, app, key, and notification. | One correct destination callback per event. | Integration log. | |
V-08Blocking | Single repository authority | Inspect developer remotes, bots, and source protections. | GitLab alone accepts approved writes. | Cutover checklist. |
Remove the scaffolding safely.
Safe after: One complete operating cycle, at least seven stable days, and owner sign-off on every blocking check.
- Create final Azure DevOps exports and archive verification evidence.
- Revoke temporary credentials, API keys, webhooks, and elevated roles.
- Remove obsolete embeds, forms, jobs, integrations, and DNS records.
- Keep the source intact through the approved retention window.
- Cancel paid plans only after billing, legal, and recovery review.
- Schedule the next GitLab backup, access, and migration-playbook review.
Built to be reviewed.
Tested 2026-07-19. Next scheduled review: 2026-10-19.
- Azure DevOps: official migration documentationAccessed 2026-07-19
- GitLab: official migration documentationAccessed 2026-07-19