One of the largest problems facing any group working on a coding project is the fact that there is no easy way to allow everyone to work on the project without conflicting with each other. This is where version control comes in. Version control is a software that manages changes to files. On a personal level, this is useful because if someone breaks something, then they can go back to a previous saved version. On a group level, version control is useful because it allows multiple people to work on the same file and save their changes separately (so that they do not muck with each other’s work). Then, when they’ve completed their work, they can merge it with their group’s work. This could be done manually line by line, but version control automates this process as best it can.
What is Git?
The program we have chosen to use for our version control is Git, with Github as our cloud-based shared repository. Git is a protocol used to record changes to the code base, while Github is a server that you can store code on using commands in Git. For further info on how to use Git, take a look at the Getting Started guide on the Git website.
To separate these two in your mind, think of Github as a server/hub that you store the shared code on. Then, each team member’s computer has a local copy of the files from the server, where all of the changes are made and recorded. When a team member is satisfied with their progress and wants to share it with the rest of the team and merge it into the final project, they push (or pull request) their code to Github.
How to set up Unity to work with Git/Github
When using Git with Unity, some special considerations have to be taken into account. Not all of the Unity files are written code, and therefore, conflicts in certain files (like the scene file or prefab files) are extremely difficult, if not impossible, to fix. To minimize problems, some changes to the default Unity configuration need to be made. Under the
Edit menu, go to
Project Settings -> Editor, and make the following changes:
Version Control Modeto
Visible Meta Files
Asset Serialization Modeto
Save the scene/project at this stage, so that the changes take effect.
The reason that we make these changes is so that if we were to run into a conflict, we might be able to fix it. If we cannot see the meta files, then we cannot fix them, and if the Asset Serialization were not in text, it would be in binary, which pretty much everyone finds incomprehensible to debug.
The last thing that we need to do before Git and Unity are set to work together is a .gitignore file for Git. A .gitignore is a special file that sits in the top level of your Git repository that tells Git what files to ignore when recording changes and pushing to your remote repository on Github.
If you look online, there are a lot of good default ones that ignore all of the appropriate files. The one change that needs to be made to work with this workflow is the addition of an
Ignored folder, in which we can stick scenes and the like that we are testing, without ever pushing them to Git. It also makes a lovely location for sticking notes about the project that you don’t want to lose. I would also ignore the
Project Settings folder, because these are specific to each computer, and do not contain information that must be distributed to all team members. Lastly, the
Standard Assets folder should be ignored, because it is rather large, and can just be downloaded individually onto each team member’s machine.
The Git Workflow
Now that Git and Unity are (hopefully) properly set up to work with each other, we need to know the workflow to minimize conflicts in the repository and keep everyone happy. If you have used Git before, then you are probably familiar with the general flow of
git commit, and
git push. This still works fine if you are working on your own, but if you are working with others, then forcing your code upon your teammates is generally frowned upon. In order to avoid tension between yourself and your team members, take heed of the below guidelines which form the Git workflow.
- Use branches. Whenever working on a new thing, check out a new branch using the following naming scheme:
name/branch-name. So if Bilbo Baggins were to make a branch to fix bugs in his code, he might name his branch
bilbo/bug-fixes. This way, we know whose branch we are looking at, and what the branch is for. This also makes it easier for us to know which branches are safe for us to delete and which ones are actively being developed.
- Assuming you are the only person working on a given branch, push and pull as normal. If you are working with more people, pushing and pulling as normal may lead to some conflicts. We’ll leave this up to the branch owner(or the person who caused the conflict) to deal with. If there’s more than just a few people working on a branch however, then you might want to create child branches off of this child branch.
- When pushing to a major branch that has multiple people working on it (something like master, or something generally not prepended with someone’s name), DO NOT PUSH/MERGE DIRECTLY. Instead, go into Github itself, and submit a pull request. All pull requests should have a minimum of two people reviewing and approving it before it gets merged into the larger branch. This is to hopefully avoid adding any faulty code. When submitting a pull request, Github will also tell us if there will be merge conflicts when we do get around to merging. Hopefully there won’t be any. If there are, we need to fix it before merging.
- If there are conflicts with pull requests, then we don’t want to merge it right away (that’ll put conflicts into our master/production branch). Instead, we want to make a new branch off of master for the sole purpose of resolving this conflict, and then merge the conflicting branch into this new branch. This allows us to create all of the conflicts that we want in this branch, and resolve them. If for some reason we mess it up, then we just delete this branch and start the merging/conflict resolution process over again. Then, once all the conflicts are resolved, we can pull request this new branch into the master branch (or whichever large branch we were attempting to PR into). This branch should still require two approvals, so that we can make sure that everything is still all right.
- SCENES. Merging scenes is one of the hardest things to do in Git and Unity, since scenes are graphical, not text-based. The best way to deal with scenes is to only allow one person at a time to work on the scene. Find some way to communicate with your team so that only one person is altering a scene at a time. This person should do their work quickly and efficiently, and then submit their code in a pull request promptly. This way, the next person gets the opportunity to work on the scene without causing conflicts, and does not need to wait too long on the previous person. Communication is very important here, because conflicts in scenes are extremely difficult to resolve. Therefore, only one person is allowed to work on a scene at a time.
We now have a complete set of guidelines for a Git workflow! Of course, there are more things that need to be agreed upon. How exactly should the project be structured? What coding standard are we going to use? How should we divide up the work? Depending on the answers to these questions, this Git workflow may or may not work; however, it is a good baseline that can be further altered to fit the project. In the end, it’s just important for your team to know how the project is organized, how to minimize conflicts, and how to review the code so only the best gets into the final product.