How to Git with Unity

By default, the Unity editor does not work well with Git. To name a few problems:

Noise: The editor manages hundreds of temporary files. Merely opening or closing the editor will create, delete, or modify some of these files. Additionally, since it’s possible to develop on and build for multiple platforms, there are many more extraneous files than you might expect to find on, say, a Rails project.

Broken object references: The editor keeps track of objects with randomly generated GUIDs. If these GUIDs are not committed to Git properly (i.e., via .meta files), the project may break when you, for example, switch branches. The more you rely on the editor, the more common and potentially catastrophic these errors are.

Unresolvable merge conflicts: Depending on your settings, the editor will save some or all of your files in binary format. If you and a team member happen to edit the same file independently – a common scenario if you use the Unity editor heavily – you will not be able to resolve the merge conflict with Git, and will have to use special tools.

Large files: A typical Unity project requires a number of large binary assets for 3D models, sounds, images, fonts, etc., which can significantly slow down your Git workflow and waste storage space.

If you use GitHub to review diffs (ex., as part of a pull request workflow), you’ll notice that changes in Unity-generated YAML files are usually not actionable. You can reduce the clutter they introduce, while preserving the ability to review them as needed, by automatically collapsing the diffs on GitHub.

Manually resolving merge conflicts between Unity-generated YAML files is very difficult and error-prone. If you followed the steps above and you’re using Unity 5 or later, you can use the editor’s Smart Merge (a.k.a, “Unity YAML Merge”). There are also various merge tools on the Unity Asset Store.

As a developer, though, I find these solutions somewhat unsatisfying. The underlying problem is not that there is a merge conflict, per se, but that a tool (the Unity editor) is translating our commands and our knowledge into a language (the Unity YAML format) that is difficult to understand, and indeed that was not really meant to be manipulated directly.

Fortunately, a code-centric approach to Unity development (ex., via Zenject) can minimize these kinds of problems, while also supporting numerous software development best practices that are often lacking in Unity development.