The complete guide to Unity & Git

Dec. 6, 2016
protect

Git is a free and open source version control system that makes it easy to track changes to your Unity projects and collaborate with developers, artists, designers, and other contributors on the same code base. It is used by over 69% of the software industry, and recent improvements to Git's handling of large assets is causing a growing number of gaming studios to migrate away from Perforce and Subversion to Git. This article will teach you how to version Unity projects with Git, track large assets such as textures and audio efficiently with Git LFS, and host and build your code with a free Bitbucket and Unity Cloud Build account.

Unity .gitignore

Unity – and scripting IDEs like MonoDevelop, Consulo, Rider, and Visual Studio – create temporary files, build assets, log files, and other generated project files that are not suitable for checking into version control. Tracking these files with Git bloats the size of your repository, and may cause horrific conflicts when multiple developers are working on the same project. You can teach Git to ignore these files by checking a special .gitignore file into your project directory:


# .gitignore

# Unity
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/Assets/AssetStoreTools*
sysinfo.txt
*.pidb.meta
 
# VS/Rider/MD/Consulo
ExportedObj/
.consulo/
.idea/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
 
# Builds
*.apk
*.unitypackage
*.app
*.exe

Based on Unity .gitignore rules generated from gitignore.io, with a few additions.

This .gitignore file should live in your Unity game directory (the immediate parent of your Assets and ProjectSettings subdirectories), even if the Unity game directory isn't the top level directory of your Git repository.

It's also worth adding .gitignore rules for special files maintained by your operating system, if you haven't already.

Unity version control settings for Git

Unity has a couple of settings, Version Control Mode and Asset Serialization Mode that force scenes, prefabs, and meta files to be written to disk in a more Git-friendly format:

Unity version control settings for Git

Navigate to Edit > Project Settings > Editor and set:

  • Version Control > Mode to Visible Meta Files

This causes Unity to write asset .meta files as normal, non-hidden files in your Assets directory. 

  • Asset Serialization > Mode to Force Text

This causes Unity to serialize Unity-generated files as YAML (text) rather than a binary format. Text-based file formats give Git a fighting chance to automatically merge changes made by multiple developers, as multiple changes to a binary file can never be automatically merged and will always conflict. 

Once you've enabled these settings you should save your project, and commit the changes to your repository. Your settings will be saved in ProjectSettings/EditorBuildSettings.asset and distributed as part of your repository, so other developers on your team won't need to make the same changes.

Handling large Unity assets in Git

Git is a distributed version control system, which means the entire history of your repository (that is, every version of every asset) is copied from the server during the clone process. This is problematic if you want to version large game assets such as spritesheets, high-resolution textures, complex models, or audio and video files alongside your source code. One 10MB spritesheet may not seem like a big deal when you first commit it, but every time you modify it another 10MB is added to your repository, which means an additional 10MB for everyone to download.

Git LFS is an extension that breaks the "distributed" nature of Git by only downloading certain large files when you actually want to work with them. By default, Git LFS only downloads the latest version of each large asset from the server when you initially clone a repository. When you switch branches, pull new changes, or checkout an earlier commit, any required assets are fetched automatically from the server.

Once you've installed Git LFS, you typically use the git lfs track command to teach Git which file patterns to track with LFS. This adds new LFS filter bindings definitions to your .gitattributes file, which should be committed and distributed as part of your repository. You can add your own definitions - a good rule of thumb is that any binary file over ~500KB should be tracked with LFS - or you can create a file named .gitattributes in the root of your repository and copy this pre-made set of definitions into it:


# .gitattributes

# Images
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
*.cubemap filter=lfs diff=lfs merge=lfs -text

# Audio
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text

# Video
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.mov filter=lfs diff=lfs merge=lfs -text

# 3D Objects
*.FBX filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.obj filter=lfs diff=lfs merge=lfs -text

# Other
*.a filter=lfs diff=lfs merge=lfs -text
*.exr filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.aif filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.rns filter=lfs diff=lfs merge=lfs -text
*.reason filter=lfs diff=lfs merge=lfs -text
*.lxo filter=lfs diff=lfs merge=lfs -text

Based on Unity .gitattributes rules defined by nemotoo, with a few additions.

Note that you can also define patterns based on wildcards or directory names – e.g. git lfs track "Assets/Textures" – but this isn't a great idea as it will cause your text-based .meta files to be tracked with Git LFS as well. 

Merging game assets with Unity SmartMerge

Once you've set your Asset Serialization mode to Force Text, Git may be able to automatically merge some changes made by different developers to .scene and .prefab files. But don't despair if you're still seeing merge conflicts: Unity ships with a Git-compatible merge tool named SmartMerge

To enable SmartMerge, you'll need to add the following snippet to your Git config. For just one repository, add it to the .git/config file in the top-level directory of your repository. To enable SmartMerge for all repositories on your system, you'll need to add it to your global Git configuration. Locations vary, it's usually ~/.gitconfig on MacOS and Linux, but you can simply run git config --global -e to open it in your system editor.  


[mergetool "unity_yaml"]
cmd = '/Applications/Unity/Unity.app/Contents/Tools/UnityYAMLMerge' merge -p "$BASE" "$REMOTE" "$LOCAL" "$MERGED"
trustExitCode = false
keepTemporaries = true
keepBackup = false
 
[merge]
tool = unity_yaml

On Windows, replace '/Applications/Unity/Unity.app/Contents/Tools/UnityYAMLMerge' with:


'C:\Program Files\Unity\Editor\Data\Tools\UnityYAMLMerge.exe'

or wherever you've installed Unity.

A quick explanation of these properties:

JikGuard.com, a high-tech security service provider focusing on game protection and anti-cheat, is committed to helping game companies solve the problem of cheats and hacks, and providing deeply integrated encryption protection solutions for games.

Read More>>