This is episode ten of Git Good, Season Two. In episode nine, we celebrated the places Git escaped to, the novelists and lawyers and scientists who found something universal in a programmer's tool. This episode is about the place Git never conquered, and the reason it never will.
Halon Entertainment makes movies before the movies exist. They are a visualization studio based in Santa Monica, with offices in Vancouver and London. When a director needs to see what a battle sequence looks like before a single frame is shot, Halon builds it. Previs, postvis, techvis, virtual production. Their work has appeared in Avatar, Life of Pi, Birdman, The Mandalorian, Kingdom of the Planet of the Apes. Oscar-winning films, built first as digital mockups on artists' screens.
For years, Halon ran two version control systems. Git for the engineers. Perforce for the artists. The engineers wrote pipeline code, plugins, automation scripts. They committed and pushed and branched, the way any software team does. The artists created three-dimensional environments, character rigs, textures, lighting setups. They checked out files from a Perforce server the way artists at studios have done since the nineteen nineties. Two teams, one product, split down the middle by what kind of files they made.
The bridge between these two worlds was clumsy. Engineers would pull plugins from Git, then push those same plugins into Perforce so the artists could access them inside Unreal Engine. Two systems, two sets of credentials, two mental models of what "saving your work" meant. Every project required configuring both systems from scratch, provisioning servers, setting up access controls twice. When a new artist joined the team, someone had to spend hours walking them through the version control setup. Not the creative tools. Not the pipeline. The version control. And even after the walkthrough, artists struggled. There were no good guides written for people who think in shapes and light instead of commands and flags. The result was that artists avoided contributing scripts and tools that could have improved the pipeline for everyone, because the tools to contribute lived in Git, and Git was not their world.
Chris Ferriter, Halon's CEO, watched this friction eat into his teams' creative time. Every hour an artist spent wrestling with version control was an hour not spent on the work that actually mattered. So Halon made a decision that runs against the gravity of the entire software industry. They did not migrate to Git. They migrated away from it. They moved everything, including the engineering workflows, onto Perforce.
We needed one system, not two. Our artists produce the majority of the data. The tooling has to work for them first.
The results were immediate. Project startup time dropped from two days to twenty minutes. Artists stopped losing work to merge conflicts that could not be resolved. The studio adopted AYON, an open-source pipeline framework that integrates with Perforce to manage workspaces automatically, so artists no longer had to think about version control at all. They just opened their files and worked.
Git cannot see a texture. This is not a limitation that can be patched. It is a design decision baked into the first lines of code Linus Torvalds wrote in two thousand five.
Git understands text. When you change a source code file, Git sees that line twelve was added, lines forty through forty-five were removed, line seventy was modified. It stores these differences as compressed deltas. A one-megabyte source file that gets ten small edits produces ten tiny records, not ten copies of the whole file. This is how Git stays fast. This is how repositories stay small. This is what makes branching and merging and diffing possible. Every feature that makes Git powerful, from three-way merges to cherry-picks to the blame command, depends on this ability to compare two versions of a file and understand what changed between them.
A texture file, a three-dimensional mesh, a character rig, an audio sample. These are opaque to Git. There are no lines. There is no meaningful difference between version one and version two that Git can express. Change one pixel in a texture and Git sees an entirely new file. It cannot tell you what changed. It cannot compress the difference efficiently. It stores the whole thing again. Do that across thousands of assets over months of production, and the repository becomes a graveyard of duplicate blobs, each one taking full space. A game that has been in development for two years might have twenty thousand revisions of binary assets. Every single one stored as a complete copy.
Git Large File Storage was supposed to fix this. Developed by GitHub and Atlassian, it replaces large files with tiny pointer files in the repository and stores the actual data on a separate server. Earlier episodes in this series have covered the architecture. What matters here is what it does not solve. LFS addresses storage. It does not address workflow. There is no file locking. Two artists can edit the same texture simultaneously, and when both try to push, one of them loses their work. There is no visual preview. Artists cannot see what a file looks like without downloading it. There is no integration with the tools artists actually use. And the bandwidth costs add up fast. GitHub gives you one gigabyte free. A single day of asset iteration on a mid-sized game can exceed that.
The fundamental problem is deeper than storage or bandwidth. Git's entire collaboration model assumes that conflicts can be resolved by comparing two versions of a file, line by line, and combining the changes. For text, this works beautifully. Two programmers edit different functions in the same file, and Git weaves their changes together automatically. For a texture, there is nothing to weave. Two artists who painted different details onto the same character skin made two different creative decisions. One wins. The other is lost. There is no merge. There is only a choice. And if nobody locked the file before they started, neither artist knows the other was working on it until one of them tries to push and discovers their afternoon of work has been wasted.
Nineteen of the top twenty triple-A game studios use Perforce. Not because they evaluated every option and chose the best one. Because Perforce solves the three problems that game development actually has, and nothing else comes close.
The first problem is scale. A modern triple-A game repository can reach ten terabytes. Not gigabytes. Terabytes. Git asks you to clone the entire repository. Perforce does not. It is centralized. Artists connect to the server and download only the files they need. A character artist working on a creature pulls that creature's textures and meshes, not the entire game world. A level designer pulls one map. The server tracks who has what and sends only the pieces each person needs.
The second problem is locking. When an artist checks out a file in Perforce, the server locks it. Nobody else can edit that file until it is checked back in. This sounds primitive next to Git's optimistic concurrency, where everyone edits freely and merges later. But for binary files, locking is not primitive. It is correct. You cannot merge two textures. You can only choose one. Locking prevents the conflict from happening in the first place. It is a pessimistic model, one that assumes conflicts are expensive and should be prevented rather than resolved. For text files, that pessimism is unnecessary. For a texture that took an artist six hours to paint, it is the only sane approach.
The third problem is the people. Game studios employ artists, animators, designers, and audio engineers alongside programmers. Most of these people have never opened a terminal. Perforce gives them a visual client with buttons. Check out. Check in. Get latest. And it integrates directly with Unreal Engine, the engine behind most of the triple-A industry. Epic Games, the company that makes Unreal, uses Perforce internally. Their tools, UnrealGameSync, Robomerge, Horde, all assume Perforce is underneath. The entire ecosystem is built around it.
I do not care which version control system has better branching. I care about whether I can open my file, do my work, and save it without calling an engineer for help. Perforce lets me do that.
That sentiment, echoed across game development forums for years, captures something the Git community has been slow to hear. Technical elegance is an engineering value. Artists value something different. They value invisibility. The best version control system, from an artist's perspective, is the one they never have to think about. Perforce, for all its expense and aging interface, achieves this. Git, even with the best wrappers, does not.
Perforce is not without its own problems. It is expensive. The interface, P4V, looks like it was designed in two thousand three, because it was. Setting it up requires a systems administrator who understands depots and streams and workspace mappings, vocabulary that is just as alien to newcomers as Git's staging area and detached HEAD. And it is centralized, which means if the server goes down, everyone stops working. For the growing world of indie game development, teams of three or five or ten people working on their first title, the cost and complexity of Perforce is a real barrier. They need something in between.
A generation of startups has noticed the gap. Anchorpoint, a German company, built a Git-based tool specifically for game studios. It handles LFS configuration automatically, so artists never see it. It adds file locking on top of Git. It shows visual previews of three-dimensional models and textures inside the version control interface. Over two hundred studios use it. The idea is to give artists the Perforce experience while keeping Git's open infrastructure underneath.
Diversion, a Y Combinator-backed startup, took a different approach. They built a cloud-native version control system from scratch, aiming at what they call Perforce power without Perforce pain. Branching in milliseconds. No servers to maintain. A free tier for small teams. They claim to cut costs by seventy percent compared to Perforce, and they integrate with Unreal, Unity, Godot, and Blender.
Unity itself saw the problem and bought the solution. In two thousand twenty, Unity Technologies acquired Codice Software, the Spanish company behind Plastic SCM, a version control system built from scratch for large binary files. They renamed it Unity Version Control and wired it directly into the Unity editor. It is not based on Git. It can talk to Git repositories through a bridge called GitSync, but underneath, it is an entirely different system, with its own storage model, its own branching model, and its own merge logic. One designed from the ground up for the kind of files Unity projects produce. The acquisition was an admission. The largest game engine company in the world looked at Git and decided to build around it rather than on top of it.
We tried Git with LFS for our first game. Three months in, cloning the repo took forty minutes and our artist quit version control entirely. She just started emailing files. We moved to Unity Version Control and the problem disappeared.
The pattern is the same everywhere. Teams start with Git because Git is free and familiar. They hit the binary wall. They either build elaborate workarounds or they move to something else. The workarounds keep getting better, but they are still workarounds. You can put a better saddle on a horse, but it will not turn into a car.
Game development is the most visible place where Git breaks, but it is not the only one. In episode nine, we mentioned DVC, Data Version Control, and promised to look at it more closely. Here is that closer look, brief because the story is simpler than it seems.
A data scientist named Dmitry Petrov spent years at Microsoft watching two worlds operate side by side without ever connecting. The software engineers had Git, pull requests, continuous integration, discipline. The data scientists had chaos. Datasets copied into new folders for each experiment. Model weights overwriting each other with no record of which version produced which results. In two thousand eighteen, Petrov and co-founder Ivan Shcheklein started a company called Iterative and released DVC.
The idea was clever. DVC mirrors Git's commands. You run dvc add, dvc push, dvc pull. The vocabulary is deliberately borrowed. But the actual data, the massive training datasets, the multi-gigabyte model files, lives in cloud storage. Amazon S3, Google Cloud Storage, Azure. What goes into the Git repository is a pointer file, a few lines of metadata that say where the real data lives. Git tracks the code and the pointers. The cloud tracks the data. The two stay in sync. A data scientist can check out any branch in Git, run dvc checkout, and get the exact version of the data that matches. Reproducibility, the thing scientists care about most, is restored.
It worked well enough that Iterative raised twenty million dollars. But in November two thousand twenty-five, something instructive happened. Iterative sold DVC to lakeFS, a company focused on enterprise data infrastructure. Petrov's team had moved on to a new project called DataChain, aimed at the multimodal AI world. DVC continues as open-source software under new stewardship, but the pivot tells you something. Even the people who built the bridge between Git and large data decided the bridge was not enough. The gap is not closing. It is widening. And the tools built to span it keep evolving into something that looks less and less like Git and more like specialized infrastructure that merely borrows Git's vocabulary as a courtesy.
There is a question buried in every story in this episode, and it is the same question that has been building since the first episode of this season. Is "use Git for everything" wisdom, or dogma?
Git for source code is wisdom. Nothing else comes close. The distributed model, the cheap branching, the merging, the vast ecosystem. For what Git was designed to do, it remains the best tool ever built for that purpose.
Git for everything else is a spectrum. For configuration files and documentation, it is excellent. For small images and binaries, it is tolerable. For game assets, scientific datasets, machine learning models, and creative files measured in gigabytes, it ranges from awkward to destructive. And the impulse to force everything into Git anyway, because GitHub is where collaboration happens, because everyone knows the commands, because not using Git feels like falling behind, that impulse is not engineering judgment. That is gravity. The same social gravity we explored in the migration episode, the pull of going where everyone else already is, except here it pulls things into a system that was never designed to hold them.
Halon Entertainment resisted that gravity. They looked at their team, looked at their work, and chose the tool that fit the work instead of the tool that fit the industry's expectations. Project startup dropped from two days to twenty minutes. Artists stopped fighting version control and started making movies. Chris Ferriter did not accomplish this by finding a better Git wrapper or a smarter LFS configuration. He accomplished it by accepting that Git was the wrong tool for the majority of his studio's output.
The healthiest teams are the ones that draw the line clearly. Git for code. The right tool for everything else. They do not treat "not in Git" as a failure. They treat it as a design decision. The same kind of design decision that made Git great in the first place. Git was built to do one thing extraordinarily well, and it does. The problems start when we ask it to be everything, when we mistake a tool's popularity for a tool's universality. A visualization studio in Santa Monica figured that out and cut their project startup by ninety-nine percent. The lesson is not that Git is flawed. The lesson is that knowing where a tool ends is as important as knowing what it does.
That was episode ten of Git Good, Season Two.
Git lfs install sets up the hooks that make Large File Storage work in a repository. Once installed, git lfs track followed by a file pattern tells Git to stop storing those files in its object database. Instead, it writes pointer files, a few lines of text that say where the real content lives on an LFS server. The actual data gets uploaded on push, downloaded on pull. It solves the repository size problem and nothing else. You still cannot diff a binary file. You still cannot merge two versions of a texture. You still cannot lock a file to prevent someone else from editing it. And you still pay for bandwidth, one gigabyte free on GitHub before the meter starts running. Think of it as Git gracefully admitting that this particular file is not its problem.