Unity + Git Simple Guide
Tags: unity3d, git, beginners
Published: 2022-07-13 04:31:08

## Table of content
1. What is Git? Why do you care?
2. Common Concept
3. Using Git
4. Git LFS
5. New Project Checklist
6. Common Scenario
7. Further Reading
8. References

## What is Git? Why do you care?
Git is a type of distributed **version control system**. When you edit a file, git can help you determine exactly what changed, who changed it, and why.

It is very important for Unity Dev to set up some sort of version control system within our project. Many things can happen with game development: 
* 💥 Deleting the wrong file(s) by accident 
* 😱 Project files become corrupted 
* 🧨 Your perfect code introduced a game-breaking bug that needs to be reverted...

Having version control in our project, gives us peace of mind. No matter what happened, as long as we _commit_ and _push_, we can always go through our change history and fall back to a previous state. 

Another reason you want to have version control is when you are working in a team. You and your teammates can work on the same project independently and git will give you the ability to **merge** those changes together.

This is by no mean a comprehensive guide to Git. Its intent is to be brief and simple to get anyone to start using git in their Unity project.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h5i5h356uxotgzja2k69.png)
 
## Common Concept

### Repository 📂
A git repository is a group of files that are monitored by git (unless specified by git ignore). You will know your project is monitored by git when you see a `.git` folder in your project.
![folder tracked by git](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35wt915y8n8a0bc5gyx1.png)
    
### Commit ⏰
A commit is a snapshot of your project. Your project history is basically a series of commits (snapshots)! You can add a commit message that describes the change you have made in the commit. 
![commit description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ojoay1swtokfor10ve3.png)
  
### Branch 🌿
If we visualize a git repository, you can see lines that **branch **out from one another.
![branches](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zam8eapubg4v3ldfsmai.png)
    
Each of that lines is a **branch**! You can think of a branch as a divergence from the main history. A git repository can have an unlimited amount of branches. With git, you can create a new branch and merge branches together. 

Why is this useful? Imagine you are working on a 2D platformer project and you want to experiment with brand new power. You are not sure if this power will break the game balance. You can create a new **branch** from the main branch and make your changes. If the changes make sense, merge your branch with the main branch. If the changes do not make sense, you can just delete your branch and go back to the main branch. Changes are isolated. It makes cleaning up so easy and simple! 

### .gitignore
`.gitignore` can often be found at the root of your git repository. It is a config file that specific files that you don't want to be tracked by git. Sample git ignore file https://github.com/github/gitignore/blob/main/Unity.gitignore

### Remote vs Local
Remember we said git is a **distributed** version control system? Your git project exists both locally on your computer and on the server. As you may guess, remote == server and local == your computer. When you are making changes and committing them, those changes only exist on your computer locally. When you push, the changes then are synced to the server (remote) and become available for everyone that has access to the repository. 

## Using Git
There are mainly 2 ways to interact with Git. You can either use a GUI (ex: Github desktop, Git Kraken, SourceTree) or the command line. 

### Using the command line 👨‍💻
We won't be covering every git command here, just enough for a simple day-to-day workflow. 

#### git add
Whenever you make a change in a project file that is tracked by git, git will recognize a change is made, but it won't be saved in the project history. 

To have your change persisted in git, you need to add the changes into a commit. That's precisely what the command `git add filename` does. 

if you want to add everything that has been changed so far, I often found myself using `git add .` and it will add all your changes to a commit. The process of taking your changes and putting them into a commit is called **staging**.

https://git-scm.com/docs/git-add

#### git commit 
So once you are done with adding changes you want to persist into a commit, you will need to actually create the commit. `git commit -m 'type commit message here'` is the command. As good practice, a commit message should describe the changes you have made in the commit.  

https://git-scm.com/docs/git-commit

#### git push
After you have committed, you may be wondering why your teammate cannot see the changes. That is because the commit currently only exists on your computer. To `push` the changes to the server, we can use the `git push` command.

https://git-scm.com/docs/git-push  

#### git pull
If someone else made a change in the branch, `git pull` will let you get the latest commit of that branch. 

https://git-scm.com/docs/git-pull

#### git branch
When you create a git repository, by default it will only have one branch (master). If you wish to create a branch, use `git branch "branch name"`.

https://git-scm.com/docs/git-branch

#### git checkout 
You can switch between branches at any time! Use `git checkout "branch name"`

https://git-scm.com/docs/git-checkout

#### git merge 
At some point, you will want to take your changes in your branch and merge it with another. `git merge "branch name"` will merge the branch specified with your current branch. 

https://git-scm.com/docs/git-merge

### Github Desktop 💻
Many developers will only use the command line and that is perfectly fine! However, I think GUI has a place in the developer toolchain. A good UI makes things more intuitive.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ji1vpoccf37zj7dubpsx.png)
 
There are many git GUI solutions out there, we will be taking a look at Github desktop.  

You can download Github desktop from https://desktop.github.com/.

Once you have the application installed, you should be greeted with this screen. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/53n9tarj6d5ctas2cqo2.png)
Find the repository you want to work with and clone(download) it onto your computer. If you already have the project cloned on your computer, you can also add it to your Github desktop.

Once you are in, you should be greeted with 2 tabs: Changes and History. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cy8sz973smyrmzft5skq.png)

As their name implies, "Changes" describe the changes you have made so far (staged or not). "History" shows the commits so far on your current branch. 

Let's focus our attention on the "Changes" tab. 
* files with a checkmark are staged files that will be included in the commit 
* green is the new additions
* red is deletion 
* orange is updates

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/og4lc2kwwe04avfmw4o9.png)
At the very bottom, you can add in your commit message. Once you click on commit to Main. A new commit will be created.

We are not done yet! Remember a commit is local. For everyone to see your changes, you will need to push them to the server. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/52il9avsykm5grwcdd5z.png)
By clicking on `Push Origin`, your local commits will now be pushed to the server and your team would be able to access them. You can also use the shortcut `ctrl + p` to push and `ctrl + shift + p` to pull. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k4npyy712d6iaiold7kq.png)
If you click on Current Branch, a dropdown should appear and you can switch between branches.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vrck5ojud2mhzwx236px.png)
When we need to merge another branch into our current branch, click on branch -> merge into the current branch and select the branch you want to merge with. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cj11a2kk4454fil7m00g.png)

That's about it for Github Desktop. For more info, you can visit their official docs at https://docs.github.com/en/desktop. 

## Git LFS
Git large file storage (aka Git LFS) is a git extension that allows git to optimize versioning for large files (think 3d models, texture, video...). I would argue it is a must-have for your unity project! 

To use git lfs, you will need the command line. If you are using Github desktop, you can open the command line via repository -> open in command prompt.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v3ik0eojx41bemlhvvuo.png)
To setup Git LFS: 
1. `git lfs install` in your project directory
2. Add a `.gitattributes` file to specify files that should be tracked under lfs, [sample](https://gist.githubusercontent.com/RingoKam/d50e8b94d74dde13bae8dd8e1798bea9/raw/7dbb3da4d84c8906f7be523fd3d3ed98726bf535/.gitattributes), alternatively, you can also use the command `git lfs track "specify file here"`. 
3. commit and push your repo

If you want to double-check and make sure your specified files are tracked under git lfs, you can use the command `git lfs ls-files`. It should display the list of files tracked under git lfs. 

## New Project Checklist
Whenever you start on a new Unity project with git, make sure the following is true.

1. Your project is a git repo
2. Git LFS is setup
3. A proper git ignore file exists

## Troubleshooting Common Scenario 🤷‍♂️

### My teammate pushed some new changes but I cannot pull 🤔
Whenever you have uncommitted changes on your local computer, and those changes are in conflict with the changes on the server, git will alarm you and prevent you from pulling. There are multiple solutions: 
1. Do you need the local changes? If not, simply discard them
2. Stash your local changes. See https://git-scm.com/docs/git-stash
3. Commit your changes to a new branch -> go back to the current branch and pull

### Merge conflicts 💀
At some point, you will run into merge conflicts. Merge conflicts happen when you are trying to merge changes that happen on the same file at the same line. Git does not know which version to use, so it gave up and requires manual intervention. I usually rely on my IDE or Git GUI to better visualize merge conflicts.

When you visit the file that has a merge conflict, it usually looks something like:
```C#
<<<<< HEAD
// things from your current commit
===========
// new changes
>>>>>>>>>> hash of commit
```
Pick the changes you want to keep! If you are using an IDE or GUI tool, there are usually options such as "Accept current changes", "Accept incoming changes", "Accept Both Changes" to help you clean up the conflicts. 

As good practice, always test out your code before completing the merge. At the very least your project should still run and compile. Never commit a broken build, it will give you bad karma.
   
### I committed files that should not be tracked by git 😅
This happens to me quite often, I would pull in a new unity package and it includes some files that I don't really want to be tracked by git. Since the file has already been committed before, adding to gitignore no longer works. What to do?

We will need to remove the file ONLY on git, but not in the file system. Use the following command `git rm --cached "filename"`. After removing it, make sure you have an updated git ignore file that will exclude the file from being tracked in the future. 

### I am ahead but also behind on my current branch? 🤯
This could happen when you and your teammate are working on the same branch, and both attempt to push their changes. The person that pushed first will have no problem, but the person after will fail. 

This is due to the second person local branch missing (behind) the commits from the server (which has commits from the first person), but locally it is also ahead because it owns commits made by you that the server does not have. 

There are many ways to resolve it. I would usually:
1) Reset the commit I am ahead by. If I am ahead by 2 commit, then `git reset HEAD~2 --soft`. This will undo your last 2 local commit, without deleting them.  
2) Stash changes 
3) git pull to get latest changes
4) Apply stashed changes, resolve any merge conflicts
5) Push 🚀

## Further Reading
Congrats! You have reached the end of this article 👏👏👏
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ao9vtqxcvvagb3hj2no.png) 
Hopefully, at this point, you have gained newfound confidence working with git. However, this should not be the end of your git journey, but the beginning. To continue, I suggest the following: 

* [learngitbranching](https://learngitbranching.js.org/
)
An interactive git playground that teaches you different git techniques. 
* [Git Workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow#:~:text=Gitflow%20is%20a%20legacy%20Git,software%20development%20and%20DevOps%20practices.) 
* [Version control & project organization best practices](https://www.youtube.com/watch?v=GEOqwtzmeP0&t=435s&ab_channel=Unity)
* [Cheatsheet](https://education.github.com/git-cheat-sheet-education.pdf)