Why locking matters
Some files cannot be merged. A 3D model in .fbx, a Photoshop file in .psd, a CAD assembly - all are binary, and concurrent edits cannot be reconciled. Without an exclusive lock, two artists can spend hours editing the same file in parallel, only to discover one's work is unreachable.
Perforce's locking model
Perforce treats files as having an explicit checkout state. Marking a file as +l in its filetype enables exclusive locking - only one user at a time can hold a writable copy. Workflows assume this:
p4 edit character.fbx # acquires exclusive lock
# ...edit...
p4 submit -d "Update rig"
# Lock released on submit
p4 lock character.fbx # explicit lock if not auto
p4 unlock character.fbx # release without submitting
The server enforces the lock; clients cannot submit changes if someone else holds the lock.
Git's native model
Git has no concept of exclusive locks. Two collaborators can edit the same file concurrently; conflicts are resolved at merge time. For text, this is fine - Git's three-way merge handles it. For binaries, the model breaks down: there is no merge, just "yours" or "mine".
Git LFS file locking
Git LFS adds a lock API:
git lfs lock character.fbx
# someone else cannot push changes to this path
git lfs unlock character.fbx
git lfs locks # list locked files
To enforce, mark files as lockable in .gitattributes:
# .gitattributes
*.fbx filter=lfs diff=lfs merge=lfs -text lockable
*.psd filter=lfs diff=lfs merge=lfs -text lockable
Without a lock, the local file is read-only; git lfs lock makes it writable. The server enforces lock ownership at push time.
Comparing the experiences
Perforce locking is integrated, fast, and tied directly to the file in the working copy. The lock is acquired at p4 edit; nothing else is needed.
Git LFS locking requires:
- An LFS server that supports the locking API (GitHub Enterprise, GitLab Premium, Gitea, custom).
.gitattributesentries marking files lockable.- Discipline to
git lfs lockbefore editing. - A push from someone holding the lock to clear it (or
git lfs unlock --force).
It works. It is not seamless.
Binary storage
Perforce stores binaries efficiently with delta compression on supported types and full storage otherwise. Bandwidth between client and server is optimised for partial syncs - artists only download the assets they need.
Git LFS stores binaries on a separate object store. Repositories stay slim; binaries fetched lazily. Hosting costs (GitHub LFS pricing, for example) can become significant on large projects.
Diff and merge
Both systems can integrate custom diff and merge tools for binaries. Perforce's p4 typemap and Git's .gitattributes serve similar roles. Quality depends on the third-party tools available, not the VCS itself.
Working tree size
Perforce's p4 sync can fetch only specified directories or filter out filetypes - p4 client defines the view. Git's sparse checkout achieves similar results but is more setup-intensive for non-engineers.
Auditability
Perforce's centralised model gives clear audit logs - who synced what, when, and what was checked out. Git's distributed model means logs depend on what reaches the server; client-side activity is invisible.
The hybrid pattern
Many studios use Git for code (sometimes via GitHub or self-hosted GitLab) and Perforce for content. The integration is mechanical: build pipelines pull from both; submission of certain assets triggers a Git commit (or vice versa). Perforce-specific tools (Helix Sync, P4VS) coexist with Git tools (gh, gitlab-cli) without conflict.
When to use each
- Binary-heavy, locking-essential workflow → Perforce.
- Code-heavy, distributed, PR-driven workflow → Git.
- Mixed → run both, integrate at the build level.
Don't fight Git into a Perforce-shaped problem. Don't fight Perforce into a Git-shaped problem. Each shines in its domain.