What you can export from Azure DevOps and what stays behind
Git content and work items leave Azure DevOps through documented paths, but secret variables cannot be read back and some pipeline context does not travel with the export. A team facing a renewal, a pricing change or a residency requirement should plan for both halves before picking a destination. Repositories are the easy part: a mirror clone carries every branch, tag and commit history, and TFVC history needs conversion before it can sit in Git. Pull requests, comments and review threads are a different family, because a plain clone does not carry them.
Work items are exported through queries and the REST API, so the practical limit is throughput rather than format. Azure DevOps delays users who exceed 200 throughput units in a five-minute window, so a large backlog export should be scheduled, paged and tested on a sample first. Pipelines split into two families. YAML definitions live in the repository as azure-pipelines.yml files and move with the code, while classic release and build definitions exist only inside the service and must be rebuilt by hand. Ask your team to inventory which kind each pipeline uses before the export starts.
Secret variables are the main gap. Their values cannot be read back through the API or the portal, so every secret must be re-entered from a source the owning team controls, such as a password manager or a secrets manager. Artifacts feeds are a fourth family: package versions can be downloaded through the feed APIs, but feed metadata, upstream source settings and permissions need their own inventory. Confirm with your Microsoft account team which export tooling and limits apply to your organization's current license, and record the result in the migration plan.
Which Azure DevOps data types export, by method and format
This table lists each Azure DevOps data type, the method that exports it, the format you receive and the documented limits that shape a bulk run. Gitea has no Azure DevOps importer, so Git history moves by mirror while work items, pull requests and feeds need their own export and import steps. The only documented Azure DevOps throughput figure is 200 throughput units in a five-minute window, so plan large exports around it.
| Data type | Export method | Output format | Limits to plan for |
|---|---|---|---|
| Git repositories | Clone or mirror with Git, including all branches and tags | Bare Git repository with full commit history | Confirm repository size and Git LFS handling on a test copy first |
| Pull requests and comments | REST API pull request endpoints, one call per item or page | JSON per pull request, including reviewer comments | Counts toward the 200 throughput unit limit in five minutes |
| TFVC history | Convert to Git before export, since TFVC cannot be cloned with Git | Changesets converted to Git commits | Validate converted history on a copy before any cut-over |
| Work items | Saved query results, plus full history through the REST API | Query results as CSV or Excel, API data as JSON | Requests above 200 throughput units in five minutes are delayed |
| YAML pipeline definitions | Included in the repository, so a Git clone exports them | Text files such as azure-pipelines.yml | No separate API call needed for the file itself |
| Classic pipeline definitions | REST API, since these live in the service rather than the repository | JSON definitions that need manual rewriting as YAML | Same throughput limit applies, so batch and pace requests |
| Secret variables | No export method returns stored secret values | Variable names only, with values not returned | Re-enter values from your own secrets store during rebuild |
| Artifacts feeds | Download package versions with feed tooling or the REST API | Native package files such as NuGet, npm, Maven and Python | Confirm total feed size and download volume before scheduling |
Why Git history moves easily but pull requests need a platform importer
Git history is the easy part of leaving Azure DevOps. Commits, branches and tags are stored in the repository itself, so a mirror clone of each Azure Repos repository carries that history to any target forge, whether GitLab, Gitea or Forgejo. The mirror does not carry anything the forge keeps in its own database. Pull requests, review threads, votes, comments, linked work items and branch policies live in Azure DevOps, not in Git, and a plain git clone --mirror leaves all of them behind. Plan the export as two separate workstreams: the Git transfer, which is largely mechanical, and the platform data transfer, which needs an importer or extraction through the Azure DevOps REST API.
For the platform data, check the importer before you commit to a target. GitLab's import documentation lists GitHub, Bitbucket Cloud, Bitbucket Server, Gitea, other GitLab instances and Git repositories by URL as import sources. Azure Repos is not on that list, so a direct GitLab import of Azure DevOps pull requests should not be assumed. Gitea's migration code includes importers for several platforms, but the Gitea import list in the supplied sources does not include Azure DevOps either. Ask the target platform's vendor or community, or test with one repository in a non-production instance, and confirm which objects come across: pull request descriptions, comment threads, reviewer votes, labels and attachments. Where no importer covers them, the fallback is a scripted extraction through the Azure DevOps REST API, which is subject to the throughput limits described in the rate limits documentation, so bulk pulls need pacing and a record of what was exported.
What does not export and the workaround for each
Git history and most work items move with a script, but several Azure DevOps records are write-only, tied to identities or held by Microsoft. Each card names one gap, the workaround that works in practice, and what to confirm in Microsoft's documentation before the cut-over date is set.
Secret pipeline variables
Variables marked as secret in Azure Pipelines and variable groups cannot be read back through the API or the UI once saved. Their values do not appear in an export, so the export shows only the names. Ask the owning teams to re-enter each value from their own vault, and rotate any credential that a secret variable held. Keep a list of every variable name by pipeline so nothing is missed at cut-over.
Service connections and their credentials
Service connections store endpoint credentials such as Azure service principals, container registry logins and generic secrets. Their stored credentials are not exportable, and the connection definition alone does not work outside Azure DevOps. Recreate each connection in GitLab, Gitea or Forgejo with a new, least-privilege identity, and confirm with Microsoft's documentation which connection fields can be retrieved before you plan the rebuild.
Personal access tokens and SSH keys
Personal access tokens and SSH keys belong to individual users and are not included in a repository export. Anything that authenticated with them, such as build scripts, webhooks and deploy jobs, will fail after the switch. Inventory where these credentials are used, issue new tokens or keys in the target forge, and confirm with Microsoft how the organization's data location affects where tokens and SSH keys are stored.
Environment approvals and checks
Environment approvals, exclusive locks and deployment checks are defined in Azure Pipelines and do not map one to one onto GitLab protected environments or Forgejo Actions environments. Record each approver, required approval count and branch restriction in a spreadsheet before you disable the old pipelines. Then rebuild the gates in the target platform and test them with a non-production deployment.
Audit history and pipeline run logs
Audit logs and historical pipeline run results are not a standard part of a repository or work item export. Decide which records your auditors need, such as who approved a production release, and export them while the organization is still reachable. Confirm with Microsoft's documentation which audit events are retained, for how long, and whether they can be exported in bulk.
Azure Artifacts feed permissions and upstream sources
Package versions can be downloaded from Artifacts feeds, but feed views, retention policies and upstream source settings are configuration rather than package content. Download the packages you still need and republish them to Gitea or Forgejo package registries, or to Pulp. Document each feed's upstream sources and permissions, and confirm with Microsoft's documentation which feed metadata the export methods return.
The sequence for a complete export, with verification at each step
This sequence moves every Azure DevOps asset class out in a fixed order, so each export has a named check before the next one starts and nothing is lost between the Git history, work items, pipelines and packages.
Inventory projects, repositories and feeds
Start by listing every Azure DevOps organization, project, Git repository, TFVC path, pipeline, work item query and Artifacts feed in a spreadsheet, with an owner and a target system for each. Record which repositories use TFVC, which pipelines are YAML and which are classic, and which feeds have upstream sources. The output is a signed-off inventory, and you know this step is done when the platform owners agree that no project is missing from it.
Mirror Git repositories and check refs
Create a bare mirror of each Git repository with git clone --mirror, then compare the list of branches and tags against the Azure Repos web view. Run git show-ref and git rev-list --count on both sides and record the commit counts per branch. The check passes when the refs and counts match for every repository, which is also the baseline for later comparisons. Mirrors carry history only, so pull requests and comments are handled in a later step.
Convert TFVC history before anything else
If any project uses Team Foundation Version Control, convert it to Git first, because Git hosts cannot import TFVC changesets directly. Decide which folders and changeset ranges to keep, run the conversion on a copy, and keep the mapping from changesets to commits. The check is a sample of files compared at the same changeset and the same file hashes in the converted Git history. Confirm the conversion tool and its limits with your Microsoft or migration partner before you start.
Export work items through queries and the REST API
Pull work items with saved WIQL queries and the Work Items REST API, including fields, links, attachments, comments and history. Azure DevOps delays users above 200 throughput units in a five-minute window, so batch requests, pause between pages, handle throttling responses with retries, and schedule large pulls outside working hours. Check the export by comparing item counts per type and state against the Boards query totals, then spot-check a sample of items for attachments and linked commits.
Export pipeline definitions and variables
Save YAML pipelines as files from each repository, and export classic release and build definitions through the REST API as JSON so their steps, triggers and task versions are preserved. Record which variables are secret, because Azure DevOps does not return secret values through the API, so those values must be re-entered from your own vault. Verify by counting pipeline definitions against the inventory and diffing exported YAML against the mirrored repository.
Pull Artifacts feeds and upstream packages
Download package versions from each Artifacts feed using the feed's own tooling, such as NuGet, npm, Maven or pip clients with the feed credentials, and record the upstream sources configured on each feed. Azure Artifacts storage is billed per GiB above a free allowance, so the export also shows how much data you are moving. Verify with a checksum for every package file and a version count per package against the feed view.
Verify the full export with checksums and a trial build
Compare the checksums of exported archives, work item counts and pipeline counts against the inventory, then import the repositories into the target forge and run one representative pipeline from the exported definitions. Mirror imports can be checked with the same ref and commit counts used in the mirroring step. The export is complete when the trial build passes, the counts match and the owners sign the reconciliation report.
How to prove the export is complete before you switch off
Do not switch off Azure DevOps until you can show, object by object, that the target matches the source. Start by freezing the source in practice: set repository branch policies and project permissions so that only a small migration group can write, and tell teams that new work during the cut-over window must be recorded in the new platform. Then run a reconciliation pass that compares branch and tag lists, the last commit hash on each branch, and the total commit count per repository. Repository content that matches by hash is the strongest evidence you will get from a Git export, because a clone or mirror either carries the same objects or it does not.
Work items and pipelines need counts that are split by type and state, not a single total. For Azure Boards, compare the number of work items per type (epics, features, user stories, bugs, tasks) and per state, using a saved query or the work item REST API, and sample a set of items to check that titles, descriptions, attachments and parent links survived. For Azure Pipelines, compare the number of pipeline definitions and recent run counts per pipeline, and list which secret variables were not exported, since their values cannot be read back. For Artifacts, compare the version list of every package in each feed against the target registry. Record the query, the date and the person who ran each check, so an auditor can repeat it.
Keep the Azure DevOps organization read-only after the cut-over rather than deleting it. Your records retention policy should set how long the final snapshot is kept and who may request access to it, and that period is a decision for your information security and legal owners, not for the migration team. Confirm with Microsoft what happens to a read-only organization on your billing plan, and confirm the export format and retention settings for any final backup you take. Log the snapshot location, its checksum and the approval for deletion, so the decommissioning step has a documented owner and a documented date.
What to plan before renewal or termination
Exporting data is only one step in leaving Azure DevOps. The contract dates, the access window, the licences that keep read-only users working and the retention rules all set how much time you have to finish the move. Confirm each term in writing with your Microsoft account team rather than assuming it from this page.
Notice and renewal dates
Find the notice period, the renewal date and any auto-renewal clause in your Azure DevOps agreement or Microsoft Customer Agreement. Work backward from the last date you can give notice to set your export and cut-over schedule. Ask your account team whether notice is given through the Azure portal, by email or through a reseller, because a missed notice can renew seats and billing for another term.
Export window before access ends
Ask when read and write access to the organization stops after your subscription ends, and whether there is a grace period. Plan exports against that date rather than the renewal date. Repositories, work items and pipeline definitions should be pulled while your admin account still has full permissions, because some API calls and downloads may fail once access is reduced.
Read-only licensing during migration
Teams often keep a few users reading old history, pull requests and work items for months after cut-over. Confirm with your account team which users can keep read-only access, whether that access needs a paid Basic seat, and whether stakeholders outside the engineering group need a seat at all. Record the answer, because it changes the seat count on your final invoice.
Data retention and deletion requests
Ask how long Microsoft keeps organization data after a subscription ends and how to request deletion. Confirm where tokens and SSH keys are stored, since they are not held in the same location as other customer data. Keep a copy of the export manifest and any audit logs your compliance team needs before you request deletion, because deleted data cannot be recovered from the service.
Azure DevOps Server lifecycle
If you run the on-premises edition, check which release you are on and where it sits in the Modern Lifecycle Policy. Under that policy, support depends on staying current, so a server that falls behind may lose support even before its listed end date. Compare an upgrade, a move to Azure DevOps Services or a replacement with self-hosted GitLab or Gitea before you commit to another term.
Questions teams ask before hiring help with an Azure DevOps export
How much effort does a full Azure DevOps export take?
Effort depends mostly on what you have, not on the export tooling. The main drivers are the number of repositories and their size, whether any history lives in TFVC, the volume of work items and their links, and how complex your pipeline definitions are. Git history can be mirrored with a clone, but issues, pull requests, reviews and wikis need a platform importer, and Gitea's importers do not cover Azure DevOps directly. Build an inventory first: count repositories, note which use TFVC, record work item counts by type, and list pipelines by YAML or classic. That inventory is the basis for any honest estimate, and it is the first thing to ask a provider to review.
Can our team export Azure DevOps data without outside help?
A small team with Git-only repositories, few work items and simple pipelines can often export the code and basic records itself. Teams with TFVC history, large work item backlogs, linked artifacts or many pipelines usually find the edge cases take more time than the copy itself. Secret variables cannot be read back from Azure DevOps, so they must be re-entered from the source of truth in your own systems. Decide early which data must be complete, such as audit-relevant history, and which can be archived read-only. Whether you do it alone or with help, the deciding factor is whether someone on the team can verify the result against the inventory.
What does the export need from our own staff?
The export needs people who know your code, your projects and your access model. Typically this includes an Azure DevOps administrator who can create tokens with the right read scopes, a team lead for each project who can confirm which repositories, boards and pipelines are still active, and someone who owns the target platform. Security or compliance staff should confirm what must be retained and where it may be stored. Plan time for these people to answer questions and review samples, because validation is where most gaps appear. Ask any provider to name the internal roles they expect from you in the written scope.
How do Azure DevOps throughput limits affect the export schedule?
Throughput limits set the pace of any bulk read through the REST API, so they shape timing more than most teams expect. Azure DevOps documents rate and usage limits, and it delays users who go above 200 throughput units in a five-minute window. A large work item export therefore runs in batches over time rather than in one pass. Pull requests and comments can add many calls per item. Ask your provider how the run will be paced, whether it can resume after a delay, and whether they will run it in a window that avoids clashes with your own automation. Check the current limits in the vendor's rate-limit documentation before you plan.
Which pipeline definitions can be exported, and what cannot?
YAML pipeline definitions are files stored in your repositories, so they move with the code and need adapting to the target CI system. Classic pipelines are defined in the Azure DevOps interface rather than in source, so they must be read through the API and rebuilt by hand in most cases. Secret variables cannot be read back once stored, so their values need to come from your password manager or secrets store, and you should plan to rotate them. Also list service connections, environments and agent pools, since these have no direct equivalent in Git hosting. Ask for a pipeline-by-pipeline mapping as part of the scope.
What should a fixed-scope quote for this export include?
A fixed-scope quote should state exactly what is in and out before work begins. Ask for the list of repositories and projects covered, how TFVC history is handled, the work item types and fields included, how attachments and wiki content are treated, and what happens to classic pipelines and secret variables. It should describe the target platform and version, the verification method, the sign-off steps, and the handover documents. Ask for the assumptions the price depends on, such as the inventory you provide and the number of review rounds. DeployOpen does not publish a price list; the quote follows from the written scope.
What recurring costs follow an export besides the one-time work?
The one-time export is only part of the cost. After cut-over, you pay for the hosting infrastructure, storage for repositories and backups, staff time for upgrades and monitoring, and any support contract you choose. GitLab publishes a maintenance policy with regular releases and required upgrade stops, so budget for upgrade work on a recurring schedule. Gitea and Forgejo also release on their own cycles. Keep the old source system readable for a defined period so you can check records, and ask any provider to state which of these recurring items they cover under a retainer and which stay with your team.
How do we confirm the export is complete before we switch off Azure DevOps?
Confirm completeness against your inventory, not against the tool's success message. Compare repository counts, branch and tag lists, commit counts per branch, and a sample of pull requests and work items with their comments and links. Check that TFVC changesets map to the history you expected, and that every classic pipeline has a rebuilt equivalent. Keep an archived copy of the source data in a location your compliance team approves, and write down what was intentionally left behind. Ask your provider to deliver this verification as a written report that your own staff can sign off.
When an export can be done in house and when a partner earns its fee
A small Git-only estate can usually be moved by an internal team. If the organization has a handful of repositories, little or no TFVC history, a short list of pipelines and few work items worth keeping, the work is mostly mirroring clones, checking branch and tag counts, and rebuilding a few pipelines by hand. Gitea and Forgejo have no Azure DevOps importer, so pull requests and review comments will not come across automatically, and the team must decide whether to archive them as read-only records or drop them. That decision, and the sign-off on what is lost, is the part an internal team should document before the first mirror runs. Confirm the exact import behavior of the target platform in its own documentation before promising anything to stakeholders.
Larger or regulated estates justify scoped outside help. The cost rises with the number of TFVC projects that need converting, the size of work item histories exported through queries and the REST API within Azure DevOps throughput limits, and the number of YAML and classic pipeline definitions that must be reviewed one by one. Secret variables cannot be read back, so each one needs a documented owner and a re-entry plan. When auditors will ask for evidence that history, permissions and access logs were preserved, the export itself becomes a control that needs a test plan, a reconciliation method and retained records. Ask any partner to show how it will reconcile item counts and commit hashes, and where the evidence will be stored.
A written scope tells you what you are buying. Expect a fixed-scope proposal that names the repositories, TFVC projects, work item types, pipeline definitions and Artifacts feeds in or out of scope, the target platform and version, the acceptance checks, the deliverables such as an inventory and a reconciliation report, and who on your side signs off on each step. DeployOpen prepares systems and evidence for compliance assessments but does not issue audit reports or attestations, so the auditor's requirements should be confirmed with your auditor before the scope is agreed. Ask for the assumptions and exclusions in writing, because the most common cost surprises come from items nobody listed.
How DeployOpen scopes and delivers an Azure DevOps data export
DeployOpen approaches an Azure DevOps data export as a fixed-scope engagement with a written inventory of what leaves the service and where it lands. The work runs inside your own infrastructure, and the result is a set of repositories, work item extracts and pipeline definitions your team can verify before any cut-over.
How we scope
- Inventory every Azure Repos Git repository and any TFVC history, noting size, branches and tags.
- Record which Boards, pipeline, Artifacts and permission data the export must cover, and which stays behind.
- Agree in writing how throughput limits, secret variables and YAML versus classic pipelines will be handled.
How we build
- Mirror Git repositories to the target forge and check commit counts, tags and branch heads against the source.
- Extract work items and pipeline definitions through queries and the REST API, paced to stay within rate limits.
- Test a trial import on a sample project, then document the field mappings and known gaps before the full run.
How we hand over
- Deliver the exported datasets, import logs, reconciliation reports and a list of items that could not be moved.
- Provide runbooks covering the export procedure, re-creation of branch policies and secret re-entry by your owners.
- Walk your engineering and security teams through the evidence so they can confirm completeness before retiring the source.
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer after the handover is accepted.
- Confirm target platform versions and upgrade paths with the forge vendor before scheduling any follow-on work.
- Quote follows from the written scope, so ask for line items covering each export component and its recurring support.

