How contribution mapping after a GitLab import works and what it takes
Teams moving repositories and issues into self-managed GitLab need authorship to survive the move, or the history of who wrote what and who reviewed it becomes unreadable. GitLab does not attach imported contributions to real accounts directly. It assigns them to placeholder users first, even when an imported author's email address matches an existing GitLab user, and an owner then reassigns each placeholder to a real user. The real user must accept the reassignment before the contribution is attributed to them. Until that happens, the contribution stays with the placeholder, so the mapping step is part of the migration rather than an optional cleanup.
For the direct transfer, GitHub, Bitbucket Server and Gitea importers, post-migration mapping is on by default. On a self-managed instance, no placeholder limit applies unless an administrator sets one. When a limit is reached, further contributions go to a single non-functional Import User, which means the attribution is lost for those items. Effort therefore scales with three things: the number of people whose contributions must be claimed, the source system (each importer produces its own identity data), and how many contributions need a human decision, such as authors who left the organization or used several accounts. Confirm with your own data how many distinct authors exist in each source before you schedule reviews.
This section covers four sources: GitHub, Bitbucket Server, Gitea, and direct transfer from another GitLab instance. Each one handles identities differently, so the first task is an inventory of source accounts, their emails and their roles, reviewed against the GitLab user list. The GitLab user mapping documentation sets out the exact mapping behavior for each importer, and you should read it against the version you plan to run before deciding who approves reassignments and whether a placeholder limit is needed.
Which contribution types map cleanly to real users and which do not
This table compares common source contribution types with how they land in GitLab before and after placeholder reassignment. Read each row as a starting assumption to test, since behavior can differ by source importer and GitLab version. The main takeaway is that authorship of content usually survives import, while acceptance, review history and memberships need explicit checks in a pilot import.
| Contribution type | How it lands after import | Reader action |
|---|---|---|
| Commits | Git history is pushed with original author names and emails, but commit authors are not linked to user accounts until mapping | Confirm author text in a pilot project and check that reassigned commits link to the right user |
| Issues | Created under placeholder users first, with original author text kept in the body | Reassign to real users and verify titles, labels and timestamps on a sample set |
| Comments on issues | Placeholder authorship until reassigned, and original text is preserved | Test threads with mixed authors to confirm attribution after acceptance |
| Merge or pull requests | Created with placeholder authors and imported review context where the importer supports it | Check the importer documentation for your source and test an open and a merged request |
| Reviews and approvals | Approval state and reviewer identity may not carry over as native GitLab approvals | Confirm approval rules are rebuilt and do not assume past sign-off is enforced |
| Memberships and roles | Imported as placeholder membership until a user accepts the reassignment | Plan who must accept before access decisions depend on the imported roles |
Documented import paths that carry contribution mapping
GitLab's import documentation lists several source types, and each one reaches the mapping step differently. The cards below cover the documented paths, the behavior to expect on each, and the checks to run before a large batch starts.
GitHub importer
The GitHub importer brings repositories, issues, pull requests and wikis into GitLab. Post-migration mapping is on by default for this path, so imported authors and comment owners start as placeholder users. Before you start, confirm which GitHub objects your team relies on, list the authors who will need reassignment, and decide who in each group will accept or reject those claims. GitHub Actions workflows do not move with the importer and need a separate rewrite.
Bitbucket Server importer
The Bitbucket Server importer maps pull requests, comments and authors into GitLab, and post-migration mapping is on by default for it. Because Bitbucket Server instances often hold years of users, many of whom have left the company, the reassignment list can be long. Export the user list from the source before the run so owners can match people to accounts and identify contributors who will need the Import User fallback.
Bitbucket Cloud importer
The Bitbucket Cloud importer follows its own data model, so the set of objects and contributor records it creates differs from the Server path. Confirm with the GitLab import documentation which pull request and comment details carry across, and test one representative repository before mapping a full workspace. Plan reassignment against the actual placeholder list the import produces, not against an assumed list from the source account directory.
Gitea importer
The Gitea importer moves repositories and issues from a lightweight Git server into GitLab. Teams often run Gitea with local accounts that do not match corporate identities, which makes the placeholder reassignment step the main manual task. Check how many Gitea accounts map to people still in your identity provider, and agree on a rule for accounts that belong to bots or former staff before the run.
Direct transfer from another GitLab
Direct transfer moves groups and projects from one GitLab instance to another and is one of the paths where post-migration mapping is on by default. Because source users can already exist on the destination, check whether your identity setup links them before the transfer so that reassignment is not repeated for people who already have accounts. Confirm the admin setting and the import source configuration on your instance version.
File export and Subversion conversion
File exports carry a package of project data that GitLab imports from a file rather than from a live source. Subversion has no direct importer, so history must first be converted to Git with external tools, and the author identities produced by that conversion become the input to your mapping. Build the author mapping file during conversion, since it determines who the placeholder users represent once the converted repository is imported.
User contribution mapping reference
Each supported path follows the same placeholder model, but the defaults and the exact objects covered depend on the source. Use the user mapping documentation as the reference for the defaults and for the placeholder limit behavior on Self-Managed instances before you run a batch. Record which path you used for each project so later audits can trace who was reassigned and when.
Why placeholder limits matter for large migrations
On a self-managed GitLab instance, no placeholder user limit applies by default. Imported contributions and memberships are assigned to placeholder users first, and the instance keeps creating them as the import runs. For a small import, this default is usually easy to live with, because owners can review and reassign each placeholder in the time available. For a large import, the absence of a limit means the number of placeholders is set by the source data, not by your team's capacity to review them. Confirm the current behavior for your GitLab version in the user mapping documentation before you rely on it.
- No limit until you set one: administrators can configure a placeholder limit, but nothing stops placeholder creation until that setting exists.
- Placeholders come before matching: GitLab assigns contributions to placeholders even when a matching email address already exists on the instance.
- Mapping is on by default for some importers: post-migration mapping is enabled by default for direct transfer, GitHub, Bitbucket Server and Gitea imports.
- Review scales with source data: the number of placeholders grows with contributors in the source history, not with the number of repositories you planned to move.
- Ask your administrator to confirm the setting: check the instance configuration and the version in use before the rehearsal import.
Check the default, the setting location and the importer you plan to use on a test instance before you size the reassignment work.
When a placeholder limit is reached, GitLab stops creating new placeholder users. Contributions beyond the limit are attributed to a single Import User. That account is non-functional, so it cannot sign in, and it cannot be used as a real owner of the work. The result is that commits, issues, pull requests or comments that would have been mapped to individual people now share one author. The history still arrives, but the link between each contribution and a specific person is lost unless someone maps it manually later.
- One shared author for overflow: every contribution past the limit lands on the same Import User, which makes per-person review difficult.
- Loss of individual attribution: for audit, blame and accountability, the author field is often what teams rely on, so overflow weakens that trail.
- Limited recovery options: the reassignment flow works on placeholders, so contributions already on the Import User need a different path that your team should test first.
- Membership effects: overflow can also affect who appears as a member, so review project and group membership after the import, not only contribution authors.
- Question to ask: confirm with GitLab support or your documentation what a reassignment from the Import User supports on your version.
Before the first production run, rehearse the import on a copy and count how many contributions land on the Import User.
The right limit depends on how many distinct contributors your source history contains and how many of them need a real account on the new instance. Contributors who have left the organization, bots, and historical authors with old email addresses often make up a large share of placeholders. Each placeholder needs an owner to decide whether it maps to a real user, and each real user needs to accept the reassignment. Those steps are the real effort in a migration, and they take longer than the technical transfer for most large sources. Plan the workload with the people who will do the reviewing, not only the people running the import.
- Count distinct authors early: extract unique author identities from the source before the import, including email variants for the same person.
- Separate active from historical contributors: active staff need a quick mapping, while former staff may be left on placeholders or mapped to a shared owner account by policy.
- Assign reviewers by project: divide placeholder review by group or project so owners can work in parallel.
- Track acceptance: users must accept or reject reassignments, so schedule time for those actions after cutover.
- Set the limit from the count: choose a limit that covers the expected distinct authors with room for variance, then document the decision.
Ask your team to produce the unique author count and a reviewer roster before the limit is set.
Large migrations combine many projects, many contributors and a cutover window in which teams need their work to be correct on day one. A placeholder limit that is too low sends important contributions to the Import User. A limit that is too high creates placeholder records that nobody reviews. The decision belongs in the migration plan, next to the importer choice, the cutover sequence and the rollback plan. Teams that delay the decision until after the import usually face a larger review queue and a harder audit story. Use a staged approach, starting with a representative subset of projects and expanding once the mapping workflow is understood.
- Decide before the first production run: the limit, the reviewers and the acceptance window should be agreed in writing.
- Rehearse on a copy: run the same importer and settings on a non-production instance and measure the placeholder count.
- Stage by group: import a representative set of projects first to test mapping for each team.
- Keep the source record: retain the source history and the author mapping file so attribution can be checked against it later.
- Document the decision: record why the limit was set, who approved it and what happens to overflow.
Confirm the limit, the reviewer plan and the rehearsal results with the migration owner before scheduling the cutover.
For regulated organizations, the author of a commit, issue or comment can be evidence in change management, access reviews and incident investigations. Auditors may ask who made a change and who approved it, and the answer should come from records that are complete and traceable. When contributions are attributed to a shared Import User, the record still exists, but it no longer answers the question about the individual. This matters most for code review and approval history, where the reviewer and author roles carry the control. Your compliance team should decide how overflow attribution will be explained before the migration, not after an auditor asks.
- Individual accountability: approval and change history depend on the person named in each record.
- Explainable mapping: keep a written record of how placeholders were mapped and who accepted each reassignment.
- Retained source evidence: preserve source exports so the original authorship can be checked against the imported data.
- Policy for unmapped history: define whether unmapped historical contributions are acceptable, and label them as such in your records.
- Compliance review: ask your auditors and compliance lead what attribution evidence they expect for migrated history.
Before the migration, agree with compliance what attribution evidence is required and confirm that the placeholder limit and review plan can provide it.
Sequence for mapping users in a pilot, parallel run and cutover
This sequence moves user mapping from a guess to a tested, owned process, so that contributions land on the right GitLab accounts when the source host is switched off. Each phase ends with a checkpoint that the next phase depends on.
Inventory source users and contributors
Export the list of accounts that authored commits, opened or commented on issues and merge requests, and held project memberships on the source host. Compare each account with the people who will exist in your GitLab identity source, and flag accounts that are bots, former staff, shared logins or contractors. The team lead for the migration owns this list, and your HR or identity team confirms who is current. The step is done when every source account has a named owner or an explicit decision to leave it unmapped.
Confirm user provisioning before importing
Decide how real users will exist in self-managed GitLab before the first import, through SAML, LDAP, SCIM or manual creation, as your authentication design allows. Reassignment only works against accounts that already exist, so accounts must be provisioned, active and able to sign in before owners are asked to accept contributions. Ask your identity team to confirm the source of truth for each active employee. The checkpoint is a list of active target accounts that matches the inventory from the previous step.
Run a pilot import of representative projects
Choose a small set of projects that cover your hardest cases: heavy contributor histories, projects with many former members, issues with comments, and at least one project from each source host you plan to import from. Import them into a non-production GitLab instance, using the same importer settings you plan to use at cutover. Compare the imported placeholder users and contribution counts with the source. The checkpoint is a written pilot report that lists which contributions were attributed to placeholders and why.
Test reassignment and acceptance with real owners
Ask a small group of real users, who represent different roles and contribution histories, to log in and review the placeholder contributions assigned to them. Have each person accept or reject the reassignment, and confirm that accepted contributions display under their accounts. Record any cases where the matching was wrong, where a user declined, or where an account could not be found. The checkpoint is a signed-off list of reassignment outcomes and a decision on how unresolved contributions will be handled.
Set placeholder limits and the import user policy
On Self-Managed no placeholder limit applies by default, but administrators can set one. Decide whether to set a limit based on the pilot's volume and your number of contributors, and document what happens when it is reached, because remaining contributions go to a single non-functional Import User. Confirm this behavior in the current GitLab user mapping documentation for your version before cutover. The checkpoint is a documented limit value, or a documented decision to run without one, approved by the migration owner.
Run a parallel period
Keep the source host available for read access while teams begin working in self-managed GitLab on the imported projects. Ask owners to complete reassignment for their contributions during this period and track the number of contributions still on placeholders. Watch for new work that was created on the source after the import, since it will need a second import or manual transfer. The checkpoint is a dated tracker showing the count of unmapped contributions decreasing and a confirmed list of projects that will not receive further changes on the source.
Perform cutover and decommission the source
Freeze writes on the source host, run the final import of any changes made since the last pass, and repeat the reassignment check for new contributions. Confirm with project owners that the accepted mappings are correct, then switch developers' remotes and links to the self-managed instance. Keep the source in read-only mode until the mapping report is archived. The step is done when the cutover record shows that all projects are imported, all remaining placeholder contributions have an owner, and the source host has been decommissioned under your retention policy.
What drives the effort of contribution mapping
This table compares the main drivers of mapping effort after a GitLab import, who typically carries each piece of work, and whether it is one-time or recurring. Read it before scoping, because the largest effort usually comes from owner review time and historical authors who have left, not from the import itself.
| Driver | Why it changes effort | Who usually pays | One-time or recurring |
|---|---|---|---|
| Number of source users | Each historical author becomes a placeholder that someone must match to a real account or leave unassigned, so effort grows with the author list. | Internal owners for review, partner for scripted matching if scoped | One-time |
| Contributions per project | Heavy history means more commits, issues and comments to check, especially where a few authors dominate and others are one-off. | Partner for analysis and reporting, internal owners for sign-off | One-time |
| Whether emails match | Matching emails can point placeholders at real accounts, but GitLab still assigns to placeholders first, so matches must be confirmed by someone. | Internal owners, with partner support for match reports | One-time |
| Share of authors who left | Former staff cannot accept reassignments, so their contributions need a decision on whether to keep the placeholder, reassign to an owner or leave as is. | Internal HR and engineering leads, with an owner decision recorded | One-time, with ongoing questions from new requests |
| Placeholder limit setting | On Self-Managed no limit applies by default, but a set limit can send later contributions to a single non-functional Import User, which needs cleanup. | Internal GitLab administrators decide, partner may configure | Setting is ongoing, cleanup is one-time |
| Number of owners who must review | More owners means more coordination, more handoffs and more places where acceptances are missed or delayed. | Internal project and group owners | One-time during cutover, then occasional |
| Accept and reject follow-up | Users must accept or reject reassignments themselves, so unanswered invitations keep work open after the import. | Internal users and owners | Recurring until closed |
What usually goes wrong with contribution mapping and how to prevent it
Most contribution mapping problems come from placeholder users that never get claimed, limits that quietly redirect work, and source systems that keep changing while the import runs. Each card below names one failure, what it looks like in the GitLab instance, and the check that catches it before cutover.
Contributions landing on the Import User
If you set a placeholder user limit and the import reaches it, remaining contributions go to a single non-functional Import User instead of named placeholders. Those commits, issues and comments then lose their individual authorship in the instance. Before the import, decide whether a limit is needed at all, set it deliberately, and compare the placeholder count from a dry run against the limit so the cap is not hit in production.
Unreassigned placeholders blocking ownership
Placeholder users hold contributions and memberships until an owner reassigns them, so projects can show authors and assignees who have no real account. Ownership and approval workflows that depend on those people stall. Assign a named owner for the reassignment queue, and review the list of unreassigned placeholders on each project before the cutover date is set.
Mismatched emails
GitLab assigns imported contributions to placeholders even when a matching email address already exists, so matching does not happen silently. Owners then have to reassign each placeholder by hand, and a wrong match can attach history to the wrong person. Export the source author list with email addresses, compare it against the directory, and resolve duplicates such as personal and work addresses before reassignment starts.
Departed authors with no reachable account
Former employees and contractors often hold a large share of historical commits and reviews, and their placeholders may never be claimed. Decide in advance whether those contributions stay attributed to a placeholder, move to a team or service account, or are recorded in a documented mapping file. Ask the business owner to sign off on that rule so the decision is not made project by project.
Reassignments nobody accepts
A reassignment is a proposal: the real user must accept it before the contributions are attributed to them. Reassignments that stay pending leave history looking unclaimed, even though the owner did the work. Send acceptance requests with a deadline, give users a short guide to accepting them, and track the pending count as a cutover metric rather than assuming the work is done once the reassignment is sent.
Running the source system in parallel without a freeze
If developers keep pushing, commenting and merging on the source host during the import, new contributions arrive after the mapping was prepared and need their own reassignment. Freezing writes on the source for the import window and documenting the cutover time keeps the mapped set stable. Confirm with the source team which activities are blocked, and plan a delta import only where your chosen method supports it.
Questions buyers ask about user mapping after a GitLab import
What drives the cost of user mapping after a GitLab import?
The main driver is the number of placeholder users and the number of contributions that need an owner's decision. Each imported contribution is first attached to a placeholder user, so a repository history with many authors creates more reassignment work than a small project with a few. Cost also depends on how many people must confirm their own mappings, how much cleanup your identity data needs before the import, and whether your team or a partner does the coordination. Ask any partner for a written scope that lists the import sources, the approximate number of users and repositories, the placeholder limit you plan to set, and who will contact each contributor. Mapping work is largely one-time for each import wave, while later support requests tend to be small.
How long does user mapping take after an import?
The duration depends less on the tooling than on how fast project owners and contributors respond. GitLab attaches imported work to placeholder users, and an owner then reassigns each one to a real user, who must accept or reject it. Teams with a small number of projects and responsive owners can finish quickly, while large organizations with many contributors who have left, changed teams or use several email addresses take longer. Plan the mapping window as its own phase after the import, and confirm with your partner or internal team how they will track which placeholders remain open at each cutover milestone.
What must our team provide before mapping users?
Before the import, prepare a current list of users from your source system with their names, usernames and email addresses, and mark people who have left or changed roles. Confirm who owns each project or group, since owners perform reassignment and need time to do it. Decide whether your instance will set a placeholder user limit, and what should happen when the limit is reached. Also confirm how your GitLab users will sign in, because accepted mappings are tied to accounts that exist in your instance. Owners should be available during the mapping window, and someone should be named to answer contributor questions.
Can our internal engineers handle user mapping without a partner?
Yes, if you have enough capacity and clear ownership. The work is mostly coordination and administration: preparing user lists, checking import results, asking owners to reassign placeholders and tracking acceptances. Internal teams with a small number of repositories and an engaged set of owners often manage it alone. A partner can help when the volume is large, when the source system has many inactive or duplicate accounts, or when the mapping must be completed on a fixed schedule. Whichever route you choose, agree on who makes the final decisions about contributors who cannot be matched.
What happens to contributions that nobody accepts?
Contributions that are never reassigned and accepted remain attached to placeholder users. Ownership of that history stays with the placeholder rather than moving to an active account, so the record of who wrote the work is incomplete. If you set a placeholder user limit and it is reached, further contributions go to a single non-functional Import User instead of separate placeholders. Decide in advance how long the mapping window stays open, who reviews unclaimed placeholders, and whether unclaimed history is acceptable for audit or licensing purposes. Ask your compliance team whether attribution gaps must be documented.
Why do placeholder limits matter for large migrations?
Placeholder limits control how many placeholder users the import can create. On Self-Managed instances no limit applies by default, but administrators can set one. When a limit is reached, contributions are assigned to one non-functional Import User, which means those contributions cannot be individually reassigned to real people through the normal placeholder flow. For a large migration with many historical authors, set the limit deliberately, estimate the placeholder count from your source data before import, and test the limit on a single repository first. Confirm the exact behavior for your GitLab version in the official mapping documentation before you rely on it.
Does user mapping require a particular GitLab license tier?
User mapping is part of the import feature set and is not described in the supplied facts as tier-specific, so confirm it with your GitLab account team or the documentation for your version before you plan around it. Licensing matters separately because the number of billed users in your instance affects cost. Placeholder users are not the same as billed seats, so ask your partner and GitLab how imported placeholders are counted before the import starts. Premium lists a price of 29 US dollars per user per month billed annually, as stated on GitLab's pricing page, but the pricing page does not settle how placeholders are counted.
How DeployOpen scopes and delivers a GitLab import with user mapping
DeployOpen starts every GitLab import with a written, fixed scope that names the source systems, the number of projects and groups, the contribution history to be preserved and the people who will sign off on reassignment. The first phase is an inventory: which repositories, issues, merge requests and memberships exist on the source, which authors appear in commit history, and how many of those authors still have active accounts in your identity provider. That inventory decides the placeholder limit question. On Self-Managed no placeholder user limit applies by default, but administrators can set one, and when the limit is reached further contributions go to a single non-functional Import User. DeployOpen recommends that you decide the limit, and who approves any exceptions, before the pilot runs, and confirm the setting in your own instance before the first production batch.
The pilot imports a representative subset of projects, including one with heavy contribution history and one with unusual membership, so the team can test reassignment end to end. Your project owners reassign placeholder users to real accounts, and each reassigned user accepts or rejects the mapping, so the pilot must include people who can actually do this in your environment. DeployOpen documents the reassignment outcome per project, supports the owners through the process and records which contributions remain unassigned. A parallel run then keeps the source system read-only or mirrored while the team checks imported data against it, followed by a cutover that is scheduled and communicated in advance. Ongoing support, including upgrades and help with late reassignment requests, is available as a retainer after the import closes.
DeployOpen does not publish a price list. A quote follows from the written scope, so it reflects the number of source instances, projects, contributors, identity integrations and the decisions still open at the start. Ask for the cost of each phase separately, which parts are one-time (inventory, pilot, cutover) and which recur (retainer support), and what changes if the placeholder limit or the number of reassignment rounds changes. Ask also who on your side owns each approval, because delays in acceptance are a common cause of extended timelines.

