Nesting Git Repos: Versioning Projects and Their Components

In this post I will use a Unity project as an example, but the same practices apply to any Git project.

As the folks at Unity work to build more tools for common version control platforms, it becomes more enticing to use Git to manage Unity projects. Not only can you reap the benefits of these platforms, but you can integrate technologies like cloud build into your workflow for faster iteration. Large File Storage (LFS) makes Git a more viable option for projects containing large binary assets, such as game art assets. These are all fantastic technologies to look into, but I want to focus this post on one that does not get as much attention: Submodules.

WhAT ARE WE TRYING TO DO?

I am a huge proponent of reusing work. Nothing makes me happier than being able reuse code and cut down my development (and headache) time.  With a little experience, one can identify common bits of code and set up class extensions, static helper functions, interfaces, etc. to reduce to time spent typing the same lines over and over. This is great, but all this code needs to go somewhere. We want to keep it in a Git repository so we can manage versions. We also want to use it across multiple projects. So what naturally follows is the question: can we nest a tools Git repository inside of a project Git repository? The answer: Yes, using Git Submodules.

lET’S DO IT!

Start off by looking over this guide on the Git website.

First we will need to make two Git repositories, one for the project and one for the submodule. For this example I will use an empty Unity project for the project and an extension class for adding some Unity specific functionality to the C# generic List class.

Let’s make the project repo first. Using your preferred method make a new repository. For newbies, here are instructions for different apps: Source Tree, GitHub, Console, GitKraken. Once you have the repo, you will want to set up a .gitignore. I use this one for Unity Projects. Then you will need to create a new Unity Project. This requires that the target folder be empty, but we have a .git folder and the .gitignore file. So you need to make the project in an empty folder that is not your repo’s root folder. Then close Unity and cut and paste the contents of the Unity project folder into the repo’s root folder. Relaunch Unity, and browse to the repo folder to open the displaced project.

I have an empty Unity 2017.2 project setup for git here. Simply fork and clone it to skip the steps in the previous paragraph. (You will need to add an Assets folder after cloning in order for Unity to recognize it as a Unity project. The empty Assets folder is not synced by git.)

Once, you have your project, you need a submodule to put in it. This will not be a Unity project itself, but most likely just a folder with a few scripts in it. To do this, initialize another remote repository on your prefer platform. Then, open up the Terminal and use the command:

git submodule add address_of_your_submodule_remote_repo Assets/name_of_folder_to_put_it_in

This will add the new repo as a submodule of the project repo in the folder you designate. Here is what the output should look like:

Now the empty repo should be nested in your project. This should be evident by the hidden .git folder in the directory you used at the end of your git submodule add command.

Now we need something to put into the submodule. I used this script. Simply creating a script or asset in the submodule folder will make sure that it is tracked by the submodule rather than the project. Now, to commit, push, or pull simply open the submodule repo in your Git app or terminal, and treat it as you would any other repository.

Using this method, you can keep certain reusable components of your project in their own separate repository, without your project repository tracking any changes directly. You can work on the submodule from within your project, publish your changes, and even use multiple submodules.

If you make changes to your submodule(s) then commit and push project changes, Sourcetree will handle the submodule check for you and even provides this handy UI.

I hope this has provided you with some insight into how to use git to make your code more modular and reusable. Below are more resources on submodules. Happy recycling!

Additional Reading

git.wiki
Chris Jean Blog
GitHub Blog