Merge Conflicts in Unity - How to avoid them?
11 tips for your Unity development team to help avoid merge conflicts.
You'll eventually encounter merge conflicts if you work with others in Unity and start using several branches in your favorite source control system. Most likely, that will happen in scene files if multiple people work on the same scene. Merging those changes may break your whole scene because no diff tool understands the semantics of those big YAML files.
The best thing is to avoid merging conflicts in the first place, so here's a little list of ideas. Let me know if you have more tips!
Tip #1: Communication is key!
This is a general tip for any team with a team size >= 2. Communication is the most essential aspect when it comes to software development. Communicate with your fellow developers on which tasks you are working on and if you're going to touch any shared stuff that might be touched by others as well. Many merge conflicts can be avoided if only one developer touches a shared thing simultaneously.
Tip #2: Use prefabs a lot
Each prefab is saved to its own file. If you change something in the prefab, only the prefab's file is changed. If you split bigger GameObject hierarchies into multiple logical prefabs, one developer can work on one logical part and another developer on another logical part without introducing merge conflicts.
But when working with prefabs, you must ensure that you're applying changes on the right prefab, mainly if you use nested prefabs.
Look at the blue line in the inspector that tells you any value changed from the underlying prefab.
Important! For example, you have an int value exposed to the Unity Inspector with a value of 5 applied to the prefab. If you use that prefab in a scene file and change that value from 5 to 6 and then back from 6 to 5 (by typing in the value), you will save the value 5 into your scene file instead of using the prefab's initial value (that will not be saved to the scene file, because that value is already being saved to the prefab's file). You'll see that with the little blue line in the inspector. You either do an Undo or right-click the value and use the "Revert" menu entry to revert your overwritten value back to the prefab's initial value.
Always check your changes because it happens super fast that you accidentally make a change and save it to your scene file.
Tip #3: Have more prefabs in a scene than non-prefabs
If you follow tip #2, your scenes will contain more prefabs than non-prefabs. Most of the time, your changes will apply to the prefab in the scene. If that's the case, your scene file won't be touched, but the prefab's file. This allows multiple developers to work on "one scene" because they are actually working on the prefabs instead.
And yes, that will not work if you need to change the transform of the GameObject in the scene because, most of the time, your prefabs need to be placed at some specific point in the scene.
Tip #4: Each developer works in his own scene
Each developer should work in his own working scene where no other developer will make a change ever. If you want, you can ignore those scenes within your version control, so they are not committed to your game.
If one needs to change a commonly used scene, some version control systems allow locking a file so no one except one developer can change it. If your version control system does not have this feature, communicate with the team that no one else currently needs to make a change to the same scene file.
Some teams simply use a shared Google Spreadsheet to write down who is working on which scene. If you're using Unity with GitHub, you can maybe leverage a plugin that allows locking files: https://github.com/spoiledcat/git-for-unity
Bonus: Depending on the thing a developer is working on, he may produce a prefab. The developer works in his own scene, creating a prefab and then putting the prefab into a commonly used scene. Now, the new prefab can be as big as it gets, but the change in the scene file is still minimal.
Tip #5: Use multiple scenes and load them additively
Unity can load multiple scenes additively. That allows you can have a scene for:
- UI
- Static Level Design
- Dynamic Level Design
- Player Control
- Enemy Control
- Debug
Etc. etc. One of many ideas. Any change to the UI will be exclusively in the UI scene. Any change to some static level content is also in its own scene. Combined with tip #2 you spread the changes into multiple smaller files instead of one big file.
Tip #6: Make commits as small as possible
This is true for anyone using a source control system. Try to make your commits as small as possible and as meaningful is possible. That makes it easier to review any change done to the code base.
Tip #7: Use ScriptableObjects
ScriptableObjects are perfect containers for static data. Often I see other devs putting a lot of data directly in their MonoBehaviours. Each data entry will be saved to either the prefab or the scene file. They can also help to split your GameObjects into multiple smaller files (and reusable data), thus reducing the risk of merge conflicts.
Tip #8: Try to use Unity's SmartMerge Tool
Unity's scene files are saved as textual YAML files. If you try to merge those files, you'll have a bad time because merge tools don't have a semantic context.
This is where Unity's SmartMerge Tool can help because it does understand the YAML files semantically and eventually can merge them better than any other tool.
You can also specify rules, e.g., how arrays shall be treated or errors due to floating point precision.
Tip #9: Reintegrate the main development branch as often as possible
Whenever a developer has a feature ready, he will merge his changes into the main development branch (e.g. develop
). Your responsibility as another developer working on your own branch is to integrate the new changes as soon as possible into your own branch. Especially if you're working on a larger system that may take some time to implement. The longer you wait for reintegration, the more likely you'll have merge conflicts.
Reintegrate early; reintegrate often!
Tip #10: Look at the diff
We know that Unity sometimes tends to change more stuff than you actually changed yourself, especially if you upgrade the Unity version and Unity has new properties for materials or other stuff. Then, it's to make a small change to your material (e.g., changing the color), but in the diff, you have a bunch of other properties changed as well. The same is true for project settings or if you forgot to save something, which will then be missing in the diff.
That's why you should always check your diff before committing, so you do not accidentally commit something you don't want to.
Tip #11: Don't break the build
Whatever you do, don't break the build. If you check in a broken build, other people may have a hard time if they integrate your changes.
The best would be to have some CI systems available that build any change done to the code base. However, Unity builds take some more time, so you only get delayed feedback, but you'll get feedback eventually!
I hope this little list of tips helps you to avoid merge conflicts in your Unity projects. If you have more suggestions, let me know!