Unity + git = friendship: part 1 set gentleman

gambar
Sistem kontrol versi git telah lama menjadi standar de facto di dunia pengembangan, tetapi bagi sebagian besar pengembang Unity bukan rahasia lagi bahwa ada sejumlah kesulitan yang terkait dengan fitur Unity yang mencegahnya digunakan secara efektif dengan git.

Berikut adalah daftar masalah umum:

  1. file yang tidak perlu masuk ke dalam repositori atau sebaliknya tidak mendapatkan yang benar
  2. banyak file besar mengembang ukuran repositori
  3. masalah dengan menggabungkan file yaml Unity
  4. hanya file itu sendiri atau hanya meta yang ditambahkan ke repositori
  5. ada folder kosong di proyek
  6. kompleksitas penomoran versi dan bangunan otomatis
  7. ketidaknyamanan menggunakan kode antara beberapa proyek

Anda dapat membaca tentang solusi untuk masalah ini terkait dengan penggunaan bersama git dan Unity di seri artikel saya.

Artikel ini akan menjelaskan solusi untuk tiga masalah pertama.

Mari kita coba menggambarkan dalam langkah-langkah metode untuk menyelesaikan setiap masalah.

Hal pertama yang perlu kita lakukan setelah membuat repositori untuk proyek Anda adalah mengkonfigurasi pengecualian, saya tidak akan membahas hal ini dengan sangat terperinci, ini adalah contoh yang bagus .

Satu-satunya komentar adalah bahwa Anda mungkin harus menambahkan beberapa pengecualian sampai akhir
! *. Dll - karena jika Anda menggunakan plugin atau aset pihak ketiga, Anda harus menyimpan dll dalam repositori dan pada Windows git mengabaikan dll secara default;
! *. obj - jika Anda menggunakan model dalam format ini, lagi-lagi pada file windows obj dapat diabaikan secara default

versi saya adalah .gitignore
# This .gitignore file should be placed at the root of your Unity project directory
#
# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
#
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/[Uu]ser[Ss]ettings/

# MemoryCaptures can get excessive in size.
# They also could contain extremely sensitive data
/[Mm]emoryCaptures/

# Asset meta data should only be ignored when the corresponding asset is also ignored
!/[Aa]ssets/**/*.meta

# Uncomment this line if you wish to ignore the asset store tools plugin
# /[Aa]ssets/AssetStoreTools*

# Autogenerated Jetbrains Rider plugin
/[Aa]ssets/Plugins/Editor/JetBrains*

# Visual Studio cache directory
.vs/

# Gradle cache directory
.gradle/

# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.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
*.unitypackage

# Crashlytics generated file
crashlytics-build.properties

# Packed Addressables
/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*

# Temporary auto-generated Android Assets
/[Aa]ssets/[Ss]treamingAssets/aa.meta
/[Aa]ssets/[Ss]treamingAssets/aa/*

# Exceptions
!*.dll
!*.obj


Langkah kedua kita akan mencoba memecahkan masalah pertumbuhan repositori dari file besar. Solusi ini adalah LFS

lebih lanjut tentang LFS
LFS β€” git, git , key-value .

, git LFS checkout .

:
www.atlassian.com/git/tutorials/git-lfs

Untuk mengkonfigurasi tipe file lfs untuk repositori kami, tambahkan .gitattributesbeberapa baris ke file di root proyek (Anda mungkin harus membuatnya, dan Windows mungkin tidak membiarkan Anda membuat file dengan ini di Explorer)

## git-lfs ##

#Image
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.cubemap filter=lfs diff=lfs merge=lfs -text
*.svg filter=lfs diff=lfs merge=lfs -text

#Audio
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text

#Video
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.mov filter=lfs diff=lfs merge=lfs -text
*.webm filter=lfs diff=lfs merge=lfs -text

#3D Object
*.FBX filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.obj filter=lfs diff=lfs merge=lfs -text

#ETC
*.a filter=lfs diff=lfs merge=lfs -text
*.exr filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.unitypackage filter=lfs diff=lfs merge=lfs -text
*.aif filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.rns filter=lfs diff=lfs merge=lfs -text
*.reason filter=lfs diff=lfs merge=lfs -text
*.lxo filter=lfs diff=lfs merge=lfs -text

sebagian besar file yang biner dan dapat berukuran cukup besar tercantum di sini. Saya akan menjelaskan sedikit:

baris yang dimulai dengan # adalah komentar;
filter=lfs diff=lfs merge=lfs- ini adalah kata ajaib yang membuat git menggunakan lfs untuk jenis file ini; -text berarti file tersebut biner dan Anda tidak perlu menggabungkannya.

Jika proyek Anda menggunakan file biner besar lainnya, tambahkan di sini nanti mengubah jenis penyimpanan file (transfer ke lfs atau hapus dari sana) akan sangat sulit.

Langkah selanjutnya adalah mencoba sedikit memperbaiki situasi dengan gabungan kompleks.
Unity termasuk utilitas UnityYAMLMerge , yang memungkinkan Anda untuk menggabungkan file yaml secara efektif. Tambahkan .gitattributesbeberapa baris ke file :

*.cs diff=csharp text
*.cginc text
*.shader text

*.mat merge=unityyamlmerge
*.anim merge=unityyamlmerge
*.unity merge=unityyamlmerge
*.prefab merge=unityyamlmerge
*.physicsMaterial2D merge=unityyamlmerge
*.physicsMaterial merge=unityyamlmerge
*.asset merge=unityyamlmerge
*.meta merge=unityyamlmerge
*.controller merge=unityyamlmerge

Biarkan saya jelaskan apa yang kami lakukan:
untuk file .cs mereka menyarankan bahwa akan ada teks menjadi kode C #;
untuk file cginc dan shader, mereka juga memilih representasi tekstual
untuk sebagian besar file Unity yaml, mereka memilih custom merge driver unityyamlmerge

Anda juga perlu mengonfigurasinya: tambahkan kode berikut ke sembarang .gitconfig, paling sederhana ke kode lokal yang terletak di jalur .git / config dari akar repositori:

[merge "unityyamlmerge"]
	name = Unity SmartMerge (UnityYamlMerge)
	driver = \"{    Unity}/Editor/Data/Tools/UnityYAMLMerge.exe\" merge -h -p --force --fallback none %O %B %A %A
	recursive = binary

Bendera -p memaksa UnityYamlMerge untuk mengubah konten file bahkan jika konflik tidak dapat diselesaikan sepenuhnya, dan sangat menyederhanakan resolusi selanjutnya dengan tangan. Sebagai contoh, ketika menggabungkan dua cabang di mana adegan yang sama diubah, menggunakan mekanisme git merge standar, kita akan melihat banyak perubahan. Saat menggunakan driver khusus, bahkan jika bidang yang sama dari komponen yang sama telah diubah, akan ada tepat 1 baris dalam konflik.

Untuk kenyamanan, saya membuat skrip kecil yang akan memungkinkan unityyamlmerge diinstal secara otomatis saat proyek pertama kali dibuka oleh Unity. Ia dapat diletakkan di mana saja di folder Aset (membutuhkan git untuk diinstal pada sistem dan didaftarkan dalam variabel PATH, mis. Dapat diakses oleh perintah git);

kelas ini
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System;

namespace GitIntegration
{
    [InitializeOnLoad]
    public class SmartMergeRegistrator
    {
        const string SmartMergeRegistratorEditorPrefsKey = "smart_merge_installed";
        const int Version = 1;
        static string VersionKey = $"{Version}_{Application.unityVersion}";

        public static string ExecuteGitWithParams(string param)
        {
            var processInfo = new System.Diagnostics.ProcessStartInfo("git");

            processInfo.UseShellExecute = false;
            processInfo.WorkingDirectory = Environment.CurrentDirectory;
            processInfo.RedirectStandardOutput = true;
            processInfo.RedirectStandardError = true;
            processInfo.CreateNoWindow = true;

            var process = new System.Diagnostics.Process();
            process.StartInfo = processInfo;
            process.StartInfo.FileName = "git";
            process.StartInfo.Arguments = param;
            process.Start();
            process.WaitForExit();

            if (process.ExitCode != 0)
                throw new Exception(process.StandardError.ReadLine());

            return process.StandardOutput.ReadLine();
        }

        [MenuItem("Tools/Git/SmartMerge registration")]
        static void SmartMergeRegister()
        {
            try
            {
                var UnityYAMLMergePath = EditorApplication.applicationContentsPath + "/Tools" + "/UnityYAMLMerge.exe";
                ExecuteGitWithParams("config merge.unityyamlmerge.name \"Unity SmartMerge (UnityYamlMerge)\"");
                ExecuteGitWithParams($"config merge.unityyamlmerge.driver \"\\\"{UnityYAMLMergePath}\\\" merge -h -p --force --fallback none %O %B %A %A\"");
                ExecuteGitWithParams("config merge.unityyamlmerge.recursive binary");
                EditorPrefs.SetString(SmartMergeRegistratorEditorPrefsKey, VersionKey);
                Debug.Log($"Succesfuly registered UnityYAMLMerge with path {UnityYAMLMergePath}");
            }
            catch (Exception e)
            {
                Debug.Log($"Fail to register UnityYAMLMerge with error: {e}");
            }
        }

        //Unity calls the static constructor when the engine opens
        static SmartMergeRegistrator()
        {
            var instaledVersionKey = EditorPrefs.GetString(SmartMergeRegistratorEditorPrefsKey);
            if (instaledVersionKey != VersionKey)
                SmartMergeRegister();
        }
    }
}
#endif

: , Unity , EditorPrefs «» , ( , Unity, ) git gitconfig .

versi terakhir dari .gitattributes
## Unity ##

*.cs diff=csharp text
*.cginc text
*.shader text

*.mat merge=unityyamlmerge
*.anim merge=unityyamlmerge
*.unity merge=unityyamlmerge
*.prefab merge=unityyamlmerge
*.physicsMaterial2D merge=unityyamlmerge
*.physicsMaterial merge=unityyamlmerge
*.asset merge=unityyamlmerge
*.meta merge=unityyamlmerge
*.controller merge=unityyamlmerge


## git-lfs ##

#Image
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.cubemap filter=lfs diff=lfs merge=lfs -text
*.svg filter=lfs diff=lfs merge=lfs -text

#Audio
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text

#Video
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.mov filter=lfs diff=lfs merge=lfs -text
*.webm filter=lfs diff=lfs merge=lfs -text

#3D Object
*.FBX filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.obj filter=lfs diff=lfs merge=lfs -text

#ETC
*.a filter=lfs diff=lfs merge=lfs -text
*.exr filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.unitypackage filter=lfs diff=lfs merge=lfs -text
*.aif filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.rns filter=lfs diff=lfs merge=lfs -text
*.reason filter=lfs diff=lfs merge=lfs -text
*.lxo filter=lfs diff=lfs merge=lfs -text


Setelah menyelesaikan langkah-langkah ini, saya sangat merekomendasikan melakukan kondisi repositori saat ini.

Proyek siap https://github.com/newnon/UnityGitHabr1
sekali lagi saya mengingatkan Anda untuk bekerja dengan benar, git harus diinstal dalam sistem dan dapat diakses dengan perintah git.

Jika Anda ingin bereksperimen
github test1 test2 test3
merge test1 test2 test3
test2 test1 test3 m_LocalPosition
E Unity Tools/Git/

All Articles