Perforce to GitLab Migration: What Moves and What Changes
This page is an honest engineering guide to moving from Perforce to GitLab — what the tooling actually does, what does not survive the migration, and the cases where you genuinely should not do it. We run these migrations, and we turn some of them down.
The short answer: the license saving is not the reason to do this. Perforce Cloud is $39 per user per month against GitLab Premium at $29 — about 26%, which is a rounding error next to the migration effort. The real drivers are ecosystem, CI/CD consolidation and developer throughput. And one thing to know before you start: GitLab has no first-party Perforce importer. Its entire official migration page points you at git p4 and warns about packfile efficiency.
Moving to a Git host other than GitLab? Our Perforce to Git migration guide compares GitLab, GitHub, Bitbucket and Azure Repos on large files, locking and repository limits. For other moves, see all our tool migration services.
When you should not migrate
These are legitimate reasons to stay, and a vendor who does not raise them is not being straight with you.
Large binary assets
Git stores a complete new compressed object for every revision of a binary — it has no delta path for most binary formats. GitLab’s own monorepo guidance lists large binary files first among monorepo problems and suggests that blobs over 10 MB should move out of Git into LFS.
Perforce’s advantage here is specific and has no Git equivalent: the +S and +Sn file type modifiers keep only the most recent N revisions of a file, deleting older ones on submit. Git has no “keep only the last N revisions of this path” mechanism. History rewriting is the only option, and GitLab documents that as destructive and irreversible.
Game development and media pipelines
Practitioners working with Unreal have documented Git LFS locking as operationally unworkable at scale — bulk-unlocking thousands of locks taking many hours, locks being global across branches, unlocking not being automatic, and lock support missing from many GUI clients. Perforce is the industry standard in these workflows for good reasons: automatic unlocking, first-class engine integration, and partial asset checkout.
Exclusive file locking on non-mergeable files
Perforce’s +l modifier means only one user at a time can open a file for editing — enforced by the server as a property of the file type, not an opt-in action by a user. See the locking section below for why the Git equivalent is materially weaker.
Terabyte-scale repositories
GitLab.com’s limits are hard: 10 GB repository size including LFS, 5 GiB maximum push. Per-project storage on Premium and Ultimate is 500 GiB, and exceeding it puts the project into a read-only state. Perforce is built for depots measured in petabytes.
Granular per-directory permissions
This is the hardest genuine gap. p4 protect gives eight access levels applied per row across user or group, host or IP, and depot path with wildcards — including exclusionary mappings. GitLab has no equivalent. Its model is role-based at project and group level; path-level read restriction has been an open feature request for years. If you have confidential middleware, export-controlled code or third-party-licensed source fenced off by protect-table rows, the only Git answer is separate repositories — which forces a repo split whether or not you wanted one.
One correction worth making, because it appears in vendor material: the claim that Git “blocks files over 100 MiB” is inaccurate. That is a GitHub push limit, not a property of Git, and GitLab’s limits are different. The genuine Perforce advantages above do not need an inaccurate one propping them up.
When migration makes sense
The cost model inverts when blobs are small. Canva runs roughly 500,000 files and 60 million lines of code in a single Git repository, with tens of thousands of commits merged weekly — file count at that scale is tractable with fsmonitor, sparse-checkout and maintenance tuning. Blob size is the real constraint, not file count.
The strongest published outcome data comes from Salesforce, which measured an 8–10% increase in overall developer productivity with Git versus Perforce across roughly 5,000 developers. That is first-party and self-reported, and should be read as such — but it is the most substantial figure available.
GitLab’s own comparison is fair on the workflow difference: Perforce branching creates an integration record for every file in the branch regardless of how many changed, against a single SHA in Git; and Perforce needed server-side shelving so others could review changes before merging, where Git shares changes without merging by default.
The mechanics: what tooling exists
git-p4 — the default, and what GitLab points at
git p4 clone //depot/path@all imports full history. Key limitations from the official documentation:
--detect-branchesinfers branches from subdirectories, and the docs concede branch relationships are difficult to infer automatically.- LFS mode cannot submit back to Perforce. Large file system support explicitly does not work with
git p4 submit— so an LFS-enabled bridge is import-only, which rules out bidirectional parallel running for binary-heavy depots. --detect-labelsis deprecated with limited usefulness.--preserve-userrequires admin privileges in Perforce.- It is considerably slower than pulling from a Git remote and creates a pack file per invocation — repack before pushing.
- Overlay mappings in
--use-client-spechave a documented bug wheregit p4can choose the wrong path.
Perforce Git Fusion — effectively retired
The latest Git Fusion documentation is from 2017, it does not appear on Perforce’s current downloads page, and current Helix Core administrator documentation describes the P4 Git Connector instead. We found no explicit end-of-life notice, so we describe it as no longer part of Perforce’s current product line rather than discontinued on a specific date. Migration guides that still present Git Fusion as an option are stale.
p4-fusion — the serious bulk converter
Salesforce’s open source C++ converter claims upwards of 100× faster than git-p4 — 3,393 changelists in 26 seconds against 42 minutes. It preserves changelists as commits and marks Perforce integrations between mapped branches as merge commits, which is materially better fidelity. Caveats: binary files are discarded by default unless you pass --includeBinaries, cyclic stream mapping graphs break it, and it generates enormous request volume against your Perforce server. Its last release was mid-2024, so check maintenance status before depending on it.
P4 Git Connector — the alternative to migrating
Worth naming honestly: Perforce’s own Git Connector mirrors Git content into a graph depot and acts as a Git server to Git clients including GitLab, supporting blended text and large binary assets. For hybrid shops it is a legitimate third option, and pretending the only choices are stay-put or migrate is not an honest framing.
What does not survive the migration
| Artifact | Outcome |
|---|---|
| Changelist numbers | Not preserved as identity. git-p4 embeds a text marker in commit messages; standard practice is to strip it. Either keep noisy messages or lose the cross-reference |
Exclusive locks (+l) | No target. Must be re-expressed as lockable in .gitattributes |
| Per-directory ACLs | No target. Redesigned as repository and group boundaries |
| Shelved changes | No bulk migration — one changelist at a time. In practice, submit or abandon before cutover |
| Client workspace mappings | Not migrated. Every developer rebuilds their working setup |
| Integration / branch history | Degraded. p4-fusion does better than git-p4, but Perforce partial and cherry-pick integrations have no Git equivalent at all |
| Labels | Partial and unreliable |
| File type modifiers | No target for +S/+Sn, +w, +k, +m. Only +x maps cleanly |
| Authorship | Preserved only with --preserve-user and Perforce admin rights. Build the user-mapping table early |
Is LFS file locking good enough for artists?
GitLab has two distinct locking mechanisms that are commonly conflated. LFS exclusive locks (all tiers) apply via .gitattributes and prevent modification on any branch. Default-branch file locks (Premium and Ultimate) are applied in the UI, enforced server-side, but apply only to the default branch — on other branches all users can still modify locked files.
Where LFS locking falls short of Perforce +l: it is advisory rather than structural — the read-only bit is a filesystem convenience, trivially cleared. It fails late: Git tells you at push time that someone else holds the lock, after the artist has done the work, where Perforce refuses the checkout up front. Locks are global across branches and unlocking is manual. And lock support is missing from many GUI clients — which matters, because the users who most need locking are the least likely to be at a terminal.
Verdict: adequate for a handful of lockable file classes touched occasionally by a small team. Not an equivalent substitute for Perforce exclusive checkout on a production art pipeline with dozens of artists and thousands of concurrent locks.
Repository splitting
A Perforce server can hold tens or hundreds of distinct projects; a Git repository normally holds one. Three forces push toward a split: permissions (every protect-table boundary that must survive becomes a repo boundary), size (GitLab.com’s 10 GB and 5 GiB ceilings), and performance.
Interestingly, practice runs both ways — several documented migrations merged multiple stream depots into a single repository for simplicity. The genuine finding is that stream topology and repository topology are independent decisions, driven by permissions, size and release cadence rather than the depot’s existing shape.
What splitting does to your build and release process is the part to plan for. A single atomic Perforce changelist spanning several directories becomes several merge requests across several repositories with no atomicity guarantee. “Sync to changelist 48211” as a reproducible build input has no cross-repo equivalent and must be replaced by a manifest, lockfile or artifact registry. Cross-repo coordination moves from the version control system into CI.
How long does it take?
Two published data points bracket an enormous range, and both are worth knowing:
- DataCore: six weeks.
git-p4plus LFS for files over 50 MB, phased team by team, main history only, multiple stream depots merged into one repository, Perforce retained read-only afterwards. The success gate was CI/CD and test framework validation before opening the repo for submissions. - Salesforce: roughly two years. Over 30 million files, hundreds of thousands of binaries, ~5,000 developers, Perforce in place for nearly two decades. A strangler pattern where Git became preferred while Perforce stayed in sync, plus a custom proxy layer so legacy tooling could work source-control-agnostically.
What both agree on: phase by team rather than big-bang, pilot on a small project first, keep Perforce alive — read-only or actively synced — rather than decommissioning at cutover, and gate on CI/CD green rather than on import completion.
The conversion run is not the schedule. History conversion is measured in hours to days. The time goes into permission redesign, repo-split decisions, build and release rework, tooling integration and retraining. Anyone quoting you “three to six months” as a standard figure is inventing it — no vendor publishes a mid-size benchmark.
What about the cost?
| Price | Notes | |
|---|---|---|
| Perforce Cloud | $39/user/month | Up to 100 users, 64 GiB storage included |
| Perforce Scale / Platform | Quote only | No published list price exists |
| GitLab Premium | $29/user/month annual | 10,000 compute minutes, 500 GiB storage |
| GitLab storage overage | $5/month per 10 GiB | = $500/month per additional TB |
The $10 per user per month delta is real — roughly $24,000 a year at 200 seats. But storage becomes metered and can erase it. Perforce Cloud bundles 64 GiB; GitLab overage runs $500 a month per additional terabyte, and exceeding quota makes projects read-only. For a binary-heavy migration, run git-sizer and git lfs migrate info --everything before pricing anything.
Admin burden shifts rather than vanishing — from protect tables, brokers and replicas to repo sprawl, runner fleets and LFS object storage. And CI/CD consolidation is frequently a larger line item than the licence delta in either direction.
Frequently asked questions
Do we keep full history, or cut over from head?
Full history costs conversion time and repository size; head-only is fast but strands history in a read-only Perforce instance. A common compromise is full history on the main line only.
How long do we run both systems in parallel?
Read-only Perforce is far cheaper than bidirectional sync. Note that git-p4‘s LFS mode cannot submit back to Perforce at all, so if you have large binaries, true bidirectional parallel running is not available through the standard tooling.
What happens to builds that pin to a changelist number?
Changelist numbers do not survive as identity. Reproducible build inputs have to be redesigned around tags, manifests or artifact versions — plan this before cutover, not after a build fails.
Is the license saving worth it on its own?
No. Teams that migrate for the 26% seat delta alone are making a mistake. Teams that migrate for the Git ecosystem, CI/CD consolidation and developer throughput have a real case, and the license difference is a bonus.
What is our rollback plan if the pilot fails?
Keeping Perforce authoritative or synced until CI/CD is green is the rollback plan. Both published case studies did exactly this.
Should we be migrating at all?
If you are binary-heavy, lock-dependent, or your permission model is load-bearing, quite possibly not — and the P4 Git Connector may give you the Git ecosystem without the migration. We would rather tell you that up front than six weeks in.
Tooling behavior, limits and pricing verified 19 September 2026 against Perforce and GitLab documentation, the git-p4 manual, and published case studies. Perforce self-managed pricing is quote-only. No vendor publishes a mid-size migration timeline benchmark — the case studies above are the available evidence.
We run these migrations — and we talk people out of them
The assessment is the valuable part: what your depot actually contains, whether your permission model survives, what the LFS storage bill looks like, and whether a Git connector gets you what you want without moving. Then we do the work if it stacks up.