Moving Microsoft Fabric workspaces between tenants with Git integration

When two organisations bring their Microsoft 365 tenants together, Fabric and Power BI workspaces are often left until last because nobody is sure how to move them. Git integration does a good part of the job, as long as you are clear about the part it does not do.

Guide · · 10 min read

What Git integration actually moves

Fabric Git integration connects a workspace to a branch in Azure DevOps or GitHub and stores each supported item as a folder of definition files. A semantic model becomes TMDL or a model.bim file, a report becomes its report definition, a notebook becomes source code, a pipeline becomes JSON. Connect a second workspace to the same branch and Fabric builds those items from the files. That is the mechanism you use between tenants: the repository is neutral ground that both sides can reach.

What it stores is definitions. It does not store the data in a lakehouse or warehouse, the credentials behind a connection, the refresh schedule on a semantic model, workspace role assignments, app audiences, subscriptions or sharing links. Some item types are not supported at all, and the supported list changes, so check Microsoft's current documentation against the items in your workspaces before you plan anything else.

A useful way to think about it: Git gets you the shape of the workspace. Everything that makes it work in a particular tenant, its data, its identities and its connections, you rebuild on purpose.

Inventory before you touch anything

Start with a list of every workspace in scope and, for each one, every item: its type, whether Git integration supports it, what it connects to and who uses it. The Fabric admin portal and the admin scanner APIs give you much of this; the rest comes from workspace owners. Pay particular attention to items that depend on items in other workspaces, such as a report in one workspace bound to a shared semantic model in another, because those references have to be rebuilt in the right order.

For each workspace, also record what Git will not carry: the capacity it sits on, role assignments, the Power BI app and its audiences, refresh schedules, gateway and cloud connections, data source credentials, row-level security membership, endorsements, sensitivity labels, subscriptions and alerts. This list becomes your rebuild checklist in the target tenant, and it is usually longer than people expect.

Then decide what not to move. Most workspaces carry abandoned reports, test notebooks and copies of copies. Moving them costs time and carries the clutter into a tenant you are trying to keep clean. Ask owners to confirm what is live, and leave the rest as a record in the repository rather than as items in the new tenant.

Note sizes as well. The largest semantic models and lakehouses decide how long data copies and first refreshes take, and they are the items most likely to need their own slot in the plan rather than moving alongside everything else.

Choose where the repository lives

Both workspaces, source and target, need to reach the repository. An Azure DevOps organisation is connected to a Microsoft Entra tenant, and whether a Fabric workspace in one tenant can connect to an Azure DevOps organisation in another depends on current product support and your settings. Check Microsoft's documentation before you commit to a design. If a cross-tenant connection is not available to you, the plain route is to push the branch from the source repository to a new repository in the target tenant's Azure DevOps organisation and connect the target workspace to that.

GitHub is not tied to an Entra tenant in the same way, which can make it a convenient bridge, but it brings its own decisions: who owns the organisation, how access tokens are issued and stored, and whether your security team is content for item definitions to sit there. Definitions can contain server names, database names and parameter values, so treat the repository as sensitive whichever platform you use.

Whichever you choose, confirm that the Git integration tenant settings are enabled in the target tenant's Fabric admin portal, and that the people doing the work are allowed to use them. It is easy to have everything else ready and then find the setting is off and the admin who can change it is on leave.

Keep the repository layout simple. Fabric lets you connect a workspace to a folder within a branch, and one folder per workspace makes it obvious which definitions belong where when several workspaces are moving through the same repository.

Prepare the target workspace

Create the workspace in the target tenant and assign it to a suitable capacity before you connect it to Git. Git integration needs a workspace on a capacity that supports it, and Fabric items such as lakehouses and notebooks need Fabric capacity. Check the capacity's region too: if data residency matters to your organisation, the target region is a decision for someone to make, not a default to accept.

Keep the target workspace empty. When you connect an empty workspace to a branch that already holds content, Fabric offers to update the workspace from Git, which is what you want. Connecting a workspace that already contains items to a populated branch forces a decision about which side wins, and that is not a decision to make under pressure on migration day.

Create connections before the sync rather than after. Cloud connections and gateway connections belong to a tenant, so identifiers from the source tenant mean nothing in the target. Install and register an on-premises data gateway in the target tenant if you need one, create the connections with the right credentials, and note their names so you can bind items to them later. Use a service account or service principal where the data source supports it, so the connections do not belong to whoever happened to set them up.

Parameterise where you can. Semantic models that take server and database names from parameters, and pipelines that read connection details from parameters or variables, are far easier to repoint than ones with values written into their queries. If the source models hard-code these, consider fixing that in the source before the move, where you can test the change against known results.

Sequence the sync

The order of work for each workspace is straightforward once the preparation is done. What makes it reliable is doing it the same way every time and recording the result.

Order matters where items depend on each other. Within a single workspace, Fabric uses logical identifiers in the definition files, so some references, such as a report bound to a semantic model in the same workspace, are resolved when the items are created in the new workspace. Other references hold fixed identifiers, and references to other workspaces point at items that do not exist in the target tenant. Move the workspaces that hold shared semantic models and lakehouses first, then move the workspaces that depend on them and repoint.

Expect some items to need attention after the sync. A notebook's default lakehouse, a pipeline activity that names a specific workspace or item, or a shortcut to a location in the old tenant can all arrive pointing at something that is not there. Open each one and check it. A sync that completes without errors tells you the definitions were created, not that the workspace works.

Move one small, low-risk workspace first as a rehearsal, end to end, including data and permissions. It shows you which items in your estate need manual fixing and gives you a realistic time for the rest.

  • Freeze changes in the source workspace and tell owners the date in advance.
  • Commit everything in the source workspace and confirm there are no uncommitted changes.
  • Tag or branch the commit you are moving, so you can always return to exactly what was moved.
  • Make that branch available to the target, either in the same repository or pushed to one the target can reach.
  • Connect the empty target workspace to the branch and folder, and update the workspace from Git.
  • Review the result and record any items that failed or were skipped.
  • Load or copy the data into lakehouses and warehouses.
  • Bind items to the new connections, set credentials and refresh every semantic model.
  • Reassign roles, publish the app, recreate schedules and hand over to owners for validation.

Moving the data

Lakehouse tables and files, warehouse tables and anything else held in OneLake stay behind. Git creates an empty lakehouse with the right name; it does not fill it. You need a separate plan for the data, and it usually falls into three groups.

Data you can rebuild from source. If a lakehouse is populated by pipelines from a system the target tenant can reach, run the pipelines in the target and let them rebuild it. This is the cleanest option, because it also proves the pipelines work in their new home before anyone relies on them.

Data you cannot rebuild: history that was loaded once, snapshots, manual uploads, files from systems that no longer exist. Copy these across, using a notebook or pipeline that reads from the source and writes to the target, or storage tooling that works with OneLake's ADLS-compatible endpoints. Authentication across tenants is the usual obstacle, so involve whoever owns identity in both tenants early, and test with one table before you schedule the rest.

Data that is not really in the workspace at all: shortcuts. A shortcut is a pointer to data held elsewhere. If the location it points to stays in the old tenant or in a storage account you are decommissioning, decide whether to recreate the shortcut against a new location, copy the data, or retire the dependency.

Identities, permissions and the things users notice

Workspace roles, item permissions, app audiences and row-level security membership all refer to users and groups by identity. Those identities are different in the target tenant, so none of it carries over. Map source groups to target groups, ideally Entra ID security groups rather than named individuals, and apply them from a script or a written checklist so the job is repeatable across workspaces.

Row-level security needs particular care. Role definitions travel with the semantic model in Git; membership assigned in the service does not. Until you reassign it, people who should see data see nothing. Resist the quick fix of giving them a workspace role instead: Admin, Member and Contributor roles are not restricted by row-level security, so that fix shows them everything. Test with a member of each role before go-live.

Users will notice the URLs. Every report, app and dashboard has a new address in the target tenant. Bookmarks, links on SharePoint pages, Teams tabs and embedded reports all break. Collect the most used links during inventory, publish a mapping from old to new, and update the embedded locations yourself rather than leaving it to users to find.

Sensitivity labels are defined per tenant, so apply the target tenant's labels after the sync. Subscriptions, alerts, comments and usage history do not move either. Tell owners in advance, so they recreate their subscriptions and are not surprised when usage metrics start again from nothing.

Rebuilding the release process

If the source tenant used deployment pipelines with development, test and production workspaces, the pipeline itself does not move. Rebuild it in the target: create the stage workspaces, assign them to the pipeline, and recreate the deployment rules for data sources and parameters, since those rules are what point each stage at the right connection.

A common pattern is to connect only the development workspace to Git and use deployment pipelines to promote to test and production. Another is to connect each stage to its own branch and promote through pull requests. Either works. The move is a good moment to choose one deliberately and write it down, because a mix of approaches across workspaces is hard to support and harder to explain to the next person.

Moving only the production workspace and rebuilding development from it is tempting, but it loses work in progress. Ask developers to commit their branches before the freeze, even unfinished ones, so nothing exists only in the source tenant when it closes.

Look for automation that pointed at the source tenant: scripts using the Fabric or Power BI REST APIs, scheduled jobs that trigger refreshes or deployments, and service principals with workspace access. These carry tenant and workspace identifiers and need updating or recreating, with new secrets or certificates.

Validating, switching off and who owns what

Validation should be done by the people who own the content, not only by the migration team. Give each owner a short list: does every report open, does every semantic model refresh, do the numbers match the source for a fixed date, can each audience see what it should and nothing more. Keep the source workspace available and read-only during this period, so comparisons are easy.

Agree an end date for the source workspace before you start. Once the target is validated, remove write access, then after a set period remove the workspace, keeping the tagged commit as the record of what moved. Leaving both live indefinitely is how you end up with two versions of the truth and a debate about which one the board pack used.

Ownership, in short: the Fabric administrator in each tenant owns capacity, tenant settings and Git configuration; the identity owner owns group mapping and cross-tenant access; workspace owners own the inventory, validation and sign-off; the migration lead owns the sequence, the freeze and the end date.

Recognise the problem?

Take the free Cloud Modernisation Assessment: 18 questions, then your score and a personalised report on what to fix first.

Get my free Cloud Modernisation Assessment