---
title: How to Git with Unity
teaser: A developer's guide to using Git with Unity projects.
tags: unity,git,vr
author: Rick Reilly
published_on: 2017-06-21
---

[Unity](https://unity3d.com/) is awesome. [Git](https://git-scm.com/) is
awesome. Wouldn’t it be nice if they got along?

# The Problem

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.

# The Solution

The solution is straightforward:

1. Add Unity-specific .gitignore settings
2. Configure Unity for version control
3. Use Git Large File Storage

## 1. Add Unity-specific .gitignore Settings

We recommend GitHub’s [Unity .gitignore template].

In addition, depending on the platforms you intend to use for development, you
should gitignore common files for [macOS](
https://github.com/github/gitignore/blob/master/Global/macOS.gitignore) and/or
[Windows](https://github.com/github/gitignore/blob/master/Global/Windows.gitignore).

## 2. Configure Unity For Version Control

With your project open in the Unity editor:

- Open the editor settings window.
  - `Edit > Project Settings > Editor`
- Make `.meta` files visible to avoid broken object references.
  - `Version Control / Mode: “Visible Meta Files”`
- Use plain text serialization to avoid unresolvable merge conflicts.
  - `Asset Serialization / Mode: “Force Text”`
- Save your changes.
  - `File > Save Project`

This will affect the following lines in your editor settings file:

- ProjectSettings/EditorSettings.asset
  - `m_ExternalVersionControlSupport: Visible Meta Files`
  - `m_SerializationMode: 2`
- If you're curious, you can read more about Unity’s YAML scene format
  [here](https://docs.unity3d.com/Manual/FormatDescription.html).

## 3.  Use Git Large File Storage

[Git Large File Storage (LFS)](https://git-lfs.github.com/) uses [Git
attributes](https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes) to
track large files with Git, while keeping them out of your actual repository.
Note that this will only work if you use [GitHub](https://github.com/) or a
server that supports the [Git LFS
API](https://github.com/git-lfs/git-lfs/tree/master/docs/api).

To set it up, download and install the Git LFS command line extension as
documented on the [Git LFS site](https://git-lfs.github.com/).

You can manually track the file types that you’d like Git LFS to manage, as
described in the Git LFS docs. However, given the numerous file types that Unity
supports, you are likely to miss a few.

Instead, feel free to use this sample `.gitattributes` file, which
comprehensively accounts for all the file types that Unity currently supports
(either natively or via conversion):

```gitattributes
# 3D models
*.3dm filter=lfs diff=lfs merge=lfs -text
*.3ds filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.c4d filter=lfs diff=lfs merge=lfs -text
*.collada filter=lfs diff=lfs merge=lfs -text
*.dae filter=lfs diff=lfs merge=lfs -text
*.dxf filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.jas filter=lfs diff=lfs merge=lfs -text
*.lws filter=lfs diff=lfs merge=lfs -text
*.lxo filter=lfs diff=lfs merge=lfs -text
*.ma filter=lfs diff=lfs merge=lfs -text
*.max filter=lfs diff=lfs merge=lfs -text
*.mb filter=lfs diff=lfs merge=lfs -text
*.obj filter=lfs diff=lfs merge=lfs -text
*.ply filter=lfs diff=lfs merge=lfs -text
*.skp filter=lfs diff=lfs merge=lfs -text
*.stl filter=lfs diff=lfs merge=lfs -text
*.ztl filter=lfs diff=lfs merge=lfs -text
# Audio
*.aif filter=lfs diff=lfs merge=lfs -text
*.aiff filter=lfs diff=lfs merge=lfs -text
*.it filter=lfs diff=lfs merge=lfs -text
*.mod filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text
*.s3m filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.xm filter=lfs diff=lfs merge=lfs -text
# Fonts
*.otf filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
# Images
*.bmp filter=lfs diff=lfs merge=lfs -text
*.exr filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.hdr filter=lfs diff=lfs merge=lfs -text
*.iff filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.pict filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
*.tiff filter=lfs diff=lfs merge=lfs -text
```

## A Bonus For GitHub Users: Automatically Collapse Generated File Diffs

If you use GitHub to review diffs (ex., as part of a [pull request
workflow](https://help.github.com/articles/about-pull-requests/)), 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](https://thoughtbot.com/blog/github-diff-supression) on GitHub.

To do so, just append this to your `.gitattributes` file:

```gitattributes
# Collapse Unity-generated files on GitHub
*.asset linguist-generated
*.mat linguist-generated
*.meta linguist-generated
*.prefab linguist-generated
*.unity linguist-generated
```

You can read more about this feature
[here](https://thoughtbot.com/blog/github-diff-supression).

# Conclusion

You should now be able to use Git to version control a Unity project as you
normally would:

- Any changes detected by Git will be legitimate, not noise generated by the
  editor.
- You will be able to commit your changes to your repo confidently, without
  fearing that the project will suddenly break when a team member tries to fetch
  it or you switch branches.
- Your large binary files can be tracked without slowing down or cluttering your
  repository.
- Changes to files generated by Unity (such as Scene files) will have diffs that
  can be inspected normally, and merge conflicts can (at least in theory) be
  resolved manually. Although...

## Actually, About Those Merge Conflicts...

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](https://docs.unity3d.com/Manual/SmartMerge.html) (a.k.a, “Unity YAML
Merge”). There are also various merge tools on the [Unity Asset
Store](https://www.assetstore.unity3d.com/en/#!/search/page=1/sortby=popularity/query=category:158).

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](https://github.com/modesttree/Zenject)) can minimize these kinds of
problems, while also supporting numerous software development best practices
that are often lacking in Unity development.

[Unity .gitignore template]: https://github.com/github/gitignore/blob/master/Unity.gitignore
