Skip to main content

11.6 - Version Control with Git

Version control is an essential tool for any software development project, including game development. It allows you to track changes, collaborate with others, and maintain a history of your project. Git is one of the most popular version control systems, and in this section, we'll explore how to use it effectively with Unity projects.

Introduction to Version Control

What is Version Control?

Version control is a system that records changes to files over time, allowing you to:

  1. Track History: See what changes were made, who made them, and when
  2. Revert to Previous States: Return to earlier versions of your project
  3. Branch and Merge: Work on different features simultaneously
  4. Collaborate: Work with others without overwriting each other's changes
  5. Back Up: Maintain copies of your project on remote servers

Why Use Version Control for Game Development?

Game development presents unique challenges that make version control particularly valuable:

  • Complex Projects: Games involve code, assets, scenes, and configurations
  • Iterative Development: Game features often require multiple iterations
  • Team Collaboration: Different team members work on different aspects
  • Experimentation: You need the freedom to try ideas without fear of breaking things
  • Asset Management: Tracking changes to large binary files

Git Basics

Git is a distributed version control system designed for speed, data integrity, and support for distributed workflows.

Key Git Concepts

  • Repository (Repo): A collection of files and their history
  • Commit: A snapshot of your project at a specific point in time
  • Branch: A separate line of development
  • Merge: Combining changes from different branches
  • Remote: A repository stored on another server (like GitHub, GitLab, or Bitbucket)
  • Clone: Creating a local copy of a remote repository
  • Push: Sending commits to a remote repository
  • Pull: Getting commits from a remote repository
  • Staging Area: A place to prepare changes before committing

Basic Git Commands

Here are some essential Git commands you'll use frequently:

# Initialize a new Git repository
git init

# Clone an existing repository
git clone https://github.com/username/repository.git

# Check the status of your repository
git status

# Add files to the staging area
git add filename.cs
git add . # Add all changes

# Commit changes
git commit -m "Add player movement system"

# Push changes to a remote repository
git push origin main

# Pull changes from a remote repository
git pull origin main

# Create a new branch
git branch feature-inventory-system

# Switch to a branch
git checkout feature-inventory-system
# Or with newer Git versions
git switch feature-inventory-system

# Create and switch to a new branch in one command
git checkout -b feature-combat-system
# Or with newer Git versions
git switch -c feature-combat-system

# Merge a branch into the current branch
git merge feature-inventory-system

# View commit history
git log

Setting Up Git for Unity Projects

Unity projects have specific requirements for version control due to their structure and the types of files they contain.

Initial Setup

  1. Install Git:

    • Download and install Git from git-scm.com
    • Configure your name and email:
      git config --global user.name "Your Name"
      git config --global user.email "your.email@example.com"
  2. Create a .gitignore File: A .gitignore file tells Git which files to ignore. Unity projects contain many generated files that shouldn't be tracked.

    Create a file named .gitignore in your project root with the following content:

    # Unity generated files
    [Ll]ibrary/
    [Tt]emp/
    [Oo]bj/
    [Bb]uild/
    [Bb]uilds/
    [Ll]ogs/
    [Uu]ser[Ss]ettings/

    # Visual Studio / VS Code files
    .vs/
    .vscode/
    *.csproj
    *.unityproj
    *.sln
    *.suo
    *.tmp
    *.user
    *.userprefs
    *.pidb
    *.booproj
    *.svd
    *.pdb
    *.mdb
    *.opendb
    *.VC.db

    # Unity3D generated meta files
    *.pidb.meta
    *.pdb.meta
    *.mdb.meta

    # Unity3D generated file on crash reports
    sysinfo.txt

    # Builds
    *.apk
    *.aab
    *.unitypackage

    # Crashlytics generated file
    crashlytics-build.properties

    # OS generated files
    .DS_Store
    .DS_Store?
    ._*
    .Spotlight-V100
    .Trashes
    ehthumbs.db
    Thumbs.db
  3. Configure Unity for Version Control:

    • Open your Unity project
    • Go to Edit > Project Settings > Editor
    • Set "Version Control Mode" to "Visible Meta Files"
    • Set "Asset Serialization Mode" to "Force Text"
    • This ensures that Unity generates text-based asset files and meta files that work well with Git
  4. Initialize the Repository:

    # Navigate to your Unity project folder
    cd path/to/your/unity/project

    # Initialize a new Git repository
    git init

    # Add the .gitignore file
    git add .gitignore

    # Commit the .gitignore file
    git commit -m "Add .gitignore for Unity project"

    # Add all project files
    git add .

    # Commit the initial project state
    git commit -m "Initial commit of Unity project"
  5. Connect to a Remote Repository (optional but recommended):

    # Add a remote repository (replace with your repository URL)
    git remote add origin https://github.com/username/repository.git

    # Push your local repository to the remote
    git push -u origin main

Unity-Specific Git Considerations

Meta Files

Unity uses .meta files to track assets and their import settings. These files are crucial for version control:

  • Each asset file has a corresponding .meta file
  • Meta files contain GUIDs that Unity uses to reference assets
  • Always commit meta files along with their assets
  • Never manually edit meta files unless you know what you're doing

Large File Storage (LFS)

Game projects often include large binary files like textures, audio, and models. Git LFS (Large File Storage) is an extension that helps manage these files:

  1. Install Git LFS:

    # Install Git LFS
    git lfs install
  2. Configure LFS for your project:

    # Track common large file types
    git lfs track "*.psd"
    git lfs track "*.png"
    git lfs track "*.jpg"
    git lfs track "*.mp3"
    git lfs track "*.wav"
    git lfs track "*.fbx"
    git lfs track "*.tga"
    git lfs track "*.tif"
    git lfs track "*.tiff"
    git lfs track "*.obj"
    git lfs track "*.mp4"
    git lfs track "*.mov"

    # Add the .gitattributes file that LFS creates
    git add .gitattributes
    git commit -m "Configure Git LFS"

Git Workflows for Unity Development

Solo Developer Workflow

Even when working alone, a structured Git workflow can help you manage your project:

  1. Main Branch: Keep a stable version of your game
  2. Feature Branches: Develop new features in separate branches
  3. Regular Commits: Make small, focused commits with clear messages
  4. Merge When Complete: Merge feature branches back to main when they're stable

Example workflow:

# Start from the main branch
git checkout main

# Create a new feature branch
git checkout -b feature-player-movement

# Make changes and commit them
git add .
git commit -m "Add basic player movement controller"

# Make more changes
git add .
git commit -m "Add jump functionality to player movement"

# When the feature is complete, merge it back to main
git checkout main
git merge feature-player-movement

# Delete the feature branch (optional)
git branch -d feature-player-movement

# Push changes to remote repository
git push origin main

Team Workflow

When working with a team, you need a more structured approach:

  1. Protected Main Branch: Keep main branch stable and protected
  2. Feature Branches: Each team member works on features in separate branches
  3. Pull Requests: Use pull requests for code review before merging
  4. Regular Pulls: Keep your local repository updated with others' changes
  5. Conflict Resolution: Learn to resolve merge conflicts effectively

Example team workflow:

# Clone the repository
git clone https://github.com/team/game-project.git
cd game-project

# Create a feature branch
git checkout -b feature-enemy-ai

# Make changes and commit them
git add .
git commit -m "Add basic enemy pathfinding"

# Push your branch to the remote repository
git push origin feature-enemy-ai

# Create a pull request (through GitHub/GitLab/Bitbucket web interface)

# Meanwhile, update your main branch
git checkout main
git pull origin main

# If needed, rebase your feature branch on the updated main
git checkout feature-enemy-ai
git rebase main

# After your pull request is approved and merged, update your local main
git checkout main
git pull origin main

# Delete your local feature branch
git branch -d feature-enemy-ai

Git-Flow

For larger teams or more complex projects, consider using Git-Flow, a branching model with specific branch types:

  • main: Production-ready code
  • develop: Integration branch for features
  • feature/*: New features
  • release/*: Preparing for a release
  • hotfix/*: Quick fixes for production issues

Best Practices for Unity and Git

Commit Practices

  1. Commit Frequently: Make small, focused commits rather than large, sweeping changes
  2. Write Clear Commit Messages: Use descriptive messages that explain what and why
  3. Commit Related Changes Together: Keep logically related changes in the same commit
  4. Commit Working Code: Try to commit code that compiles and doesn't break existing functionality

Example of good commit messages:

Add player movement controller
- Implement basic WASD movement
- Add sprint functionality with shift key
- Include smooth acceleration and deceleration

Scene Management

Unity scenes can be challenging to merge when multiple people make changes:

  1. Scene Division: Divide your game into multiple scenes when possible
  2. Prefab Everything: Use prefabs for complex objects instead of modifying them directly in scenes
  3. Scene Ownership: Assign "ownership" of scenes to specific team members
  4. Unity Scene Merging Tools: Consider using tools like Unity Smart Merge or commercial solutions

Asset Organization

Organize your assets to minimize merge conflicts:

  1. Folder Structure: Create a clear, logical folder structure
  2. Asset Naming: Use consistent naming conventions
  3. Separation of Concerns: Keep different types of assets in different folders

Example folder structure:

Assets/
├── Animations/
├── Audio/
│ ├── Music/
│ └── SFX/
├── Materials/
├── Models/
├── Prefabs/
├── Scenes/
├── Scripts/
│ ├── AI/
│ ├── Player/
│ ├── UI/
│ └── Utilities/
├── Shaders/
├── Textures/
└── UI/

Handling Large Files

  1. Use Git LFS: Track large binary files with Git LFS
  2. Asset Optimization: Compress textures and audio when possible
  3. External Asset Storage: Consider keeping very large assets outside the repository

Resolving Merge Conflicts

Merge conflicts occur when Git can't automatically merge changes:

  1. Text-Based Assets: For scripts and text-based assets, use standard Git merge tools
  2. Unity Assets: For Unity-specific assets, use Unity's Smart Merge utility
  3. Binary Files: For binary files, usually one version must be chosen over the other
  4. Communication: Coordinate with team members to avoid conflicts in the first place

Basic conflict resolution:

# When a merge conflict occurs
git status # See which files have conflicts

# Open the conflicted files in your editor and resolve the conflicts
# Look for markers like:
# <<<<<<< HEAD
# your changes
# =======
# their changes
# >>>>>>> branch-name

# After resolving, mark the files as resolved
git add resolved-file.cs

# Complete the merge
git commit

Unity Collaboration Tools

In addition to Git, Unity offers its own collaboration tools:

Unity Collaborate / Unity Teams

Unity's built-in version control solution:

  • Integrated directly into the Unity Editor
  • Simplified workflow for non-technical team members
  • Automatic large file handling
  • Limited branching capabilities compared to Git

Unity Asset Server (Legacy)

An older version control solution that has been deprecated in favor of Unity Collaborate.

Plastic SCM

Plastic SCM is a version control system acquired by Unity:

  • Designed for handling binary files and large projects
  • Strong branching and merging capabilities
  • Visual tools for conflict resolution
  • Integration with Unity Editor

Practical Example: Setting Up a Unity Project with Git

Let's walk through a complete example of setting up a new Unity project with Git:

1. Create a New Unity Project

  1. Open Unity Hub
  2. Click "New Project"
  3. Select a template (e.g., 3D Core)
  4. Name your project (e.g., "AdventureGame")
  5. Choose a location
  6. Click "Create Project"

2. Configure Unity for Version Control

  1. In Unity, go to Edit > Project Settings > Editor
  2. Set "Version Control Mode" to "Visible Meta Files"
  3. Set "Asset Serialization Mode" to "Force Text"
  4. Save the project (File > Save Project)

3. Initialize Git Repository

Open a terminal/command prompt and navigate to your project folder:

cd path/to/AdventureGame

# Initialize Git repository
git init

# Create a .gitignore file
# (Copy the Unity .gitignore content from earlier in this section)
# Save it as .gitignore in your project folder

# Add .gitignore to the repository
git add .gitignore
git commit -m "Add .gitignore for Unity project"
# Install Git LFS if you haven't already
git lfs install

# Track common large file types
git lfs track "*.psd"
git lfs track "*.png"
git lfs track "*.jpg"
git lfs track "*.mp3"
git lfs track "*.wav"
git lfs track "*.fbx"

# Add the .gitattributes file
git add .gitattributes
git commit -m "Configure Git LFS for large assets"

5. Make Your First Commit

# Add all project files
git add .

# Commit the initial project state
git commit -m "Initial commit of Unity project"

6. Create a Remote Repository (GitHub Example)

  1. Go to GitHub and sign in
  2. Click the "+" icon in the top-right corner and select "New repository"
  3. Name your repository (e.g., "AdventureGame")
  4. Leave "Initialize this repository with a README" unchecked
  5. Click "Create repository"

7. Connect and Push to Remote Repository

# Add the remote repository
git remote add origin https://github.com/yourusername/AdventureGame.git

# Push your local repository to GitHub
git push -u origin main

8. Create a Development Branch

# Create and switch to a development branch
git checkout -b develop

# Push the develop branch to GitHub
git push -u origin develop

9. Start Working on a Feature

# Create a feature branch from develop
git checkout -b feature-player-controller develop

# Make changes in Unity...

# Commit your changes
git add .
git commit -m "Add basic player controller script"

# Push the feature branch to GitHub
git push -u origin feature-player-controller

10. Merge the Feature

When your feature is complete:

# Switch to the develop branch
git checkout develop

# Merge the feature branch
git merge feature-player-controller

# Push the updated develop branch to GitHub
git push origin develop

# Delete the feature branch (optional)
git branch -d feature-player-controller
git push origin --delete feature-player-controller

Troubleshooting Common Git Issues in Unity

Issue: Large File Rejection

Problem: GitHub or other Git hosts reject pushes with large files.

Solution:

  1. Set up Git LFS
  2. Track the large file types
  3. Remove the large files from Git history if they were committed before setting up LFS
# Remove large files from Git history (use with caution!)
git filter-branch --force --tree-filter 'rm -f path/to/large/file.psd' HEAD
git push --force origin main

Issue: Meta File Conflicts

Problem: Conflicts in .meta files.

Solution:

  1. Be careful when resolving meta file conflicts
  2. When in doubt, keep the newer version of the meta file
  3. If assets are missing references after a merge, check the meta files

Issue: Scene Merge Conflicts

Problem: Multiple people modified the same scene, causing conflicts.

Solution:

  1. Use Unity's Smart Merge utility
  2. Consider scene ownership policies
  3. Break down scenes into smaller, more manageable scenes
  4. Use prefabs for complex objects

Issue: Missing References After Pull

Problem: After pulling changes, some assets have missing references.

Solution:

  1. Ensure all meta files were properly committed and pulled
  2. Check if the referenced assets exist in the project
  3. Rebuild the Library folder by closing Unity and deleting the Library folder, then reopening the project
# Close Unity first!
rm -rf Library
# Then reopen the project in Unity

Advanced Git Techniques for Unity

Git Hooks

Git hooks are scripts that run automatically when certain Git events occur:

# Example pre-commit hook to check for large files
# Save as .git/hooks/pre-commit and make executable

#!/bin/sh
# Check for files larger than 100MB
large_files=$(find . -type f -size +100M -not -path "./.git/*")

if [ -n "$large_files" ]; then
echo "Error: Attempting to commit large files:"
echo "$large_files"
echo "Please use Git LFS for large files."
exit 1
fi

exit 0

Git Submodules

Submodules allow you to include other Git repositories within your project:

# Add a submodule for a shared asset library
git submodule add https://github.com/team/shared-assets.git Assets/SharedAssets

# Update submodules after cloning
git submodule update --init --recursive

Automated Build Systems

Integrate Git with CI/CD systems for automated builds:

  • GitHub Actions: Set up workflows to build your Unity project on push
  • Jenkins: Configure build jobs triggered by Git commits
  • Unity Cloud Build: Connect your Git repository for automatic builds

Example GitHub Actions workflow for Unity:

name: Build Unity Project

on:
push:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
lfs: true

- uses: game-ci/unity-builder@v2
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
with:
targetPlatform: WebGL

- uses: actions/upload-artifact@v2
with:
name: Build
path: build

Conclusion

Version control with Git is an essential skill for Unity developers. It provides a safety net for your code, facilitates collaboration, and helps maintain a history of your project's development. By following the best practices outlined in this section, you can effectively manage your Unity projects with Git, whether you're working alone or as part of a team.

Remember these key points:

  • Configure Unity properly for version control
  • Use a good .gitignore file
  • Commit frequently with clear messages
  • Use branches for features and experiments
  • Handle large files with Git LFS
  • Organize your project to minimize merge conflicts
  • Learn to resolve conflicts effectively

As you continue your journey in Unity development, your Git skills will become increasingly valuable, allowing you to work more efficiently and collaborate more effectively.

Unity Relevance

Unity Technologies recognizes the importance of version control and has been improving Unity's compatibility with Git over the years. The "Force Text" serialization mode and Smart Merge utility are examples of features designed specifically to work better with version control systems.

For larger teams or studios, Unity also offers Unity Teams (formerly Collaborate) as an integrated solution, and has acquired Plastic SCM as a more powerful alternative to Git for game development.

Regardless of which system you choose, version control should be an integral part of your Unity development workflow from the beginning of your project.

In the next section, we'll wrap up this module with a comprehensive preparation guide for your Unity journey, bringing together everything you've learned about C# and preparing you for the exciting world of Unity game development.