Einheit + Git = Freundschaft: Teil 1 Gentleman-Set

Bild
Das Git-Versionskontrollsystem ist seit langem zum De-facto-Standard in der Entwicklungswelt geworden, aber für die meisten Unity-Entwickler ist es kein Geheimnis, dass mit Unity-Funktionen eine Reihe von Schwierigkeiten verbunden sind, die verhindern, dass es effektiv mit Git verwendet wird.

Hier ist eine Liste der häufigsten Probleme:

  1. unnötige Dateien fallen in das Repository oder umgekehrt
  2. Viele große Dateien erhöhen die Größe des Repositorys
  3. Problem mit Merge Yaml Unity-Dateien
  4. Dem Repository wird nur die Datei selbst oder nur Meta hinzugefügt
  5. Das Projekt enthält leere Ordner
  6. Komplexität der automatischen Nummerierung von Versionen und Builds
  7. Unannehmlichkeiten bei der Verwendung von Code zwischen mehreren Projekten

Über die Lösung dieser Probleme im Zusammenhang mit der gemeinsamen Verwendung von Git und Unity können Sie in meiner Artikelserie lesen.

Dieser Artikel beschreibt die Lösung der ersten drei Probleme.

Lassen Sie uns versuchen, die Methoden zur Lösung der einzelnen Probleme schrittweise zu beschreiben.

Nachdem wir das Repository für Ihr Projekt erstellt haben, müssen wir zunächst Ausnahmen konfigurieren. Darauf werde ich nicht näher eingehen. Hier ist ein gutes Beispiel .

Die einzige Bemerkung ist, dass Sie am Ende wahrscheinlich ein paar Ausnahmen hinzufügen sollten
! *. Dll - Wenn Sie Plugins oder Assets von Drittanbietern verwenden, müssen Sie die DLL im Repository speichern und unter Windows ignoriert Git die DLL standardmäßig.
! *. obj - Wenn Sie Modelle in diesem Format verwenden, können obj-Dateien in Windows standardmäßig ignoriert werden

Meine Version ist .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


Im zweiten Schritt werden wir versuchen, das Problem des Repository-Wachstums aus großen Dateien zu lösen. Diese Lösung ist LFS

mehr über LFS
LFS — git, git , key-value .

, git LFS checkout .

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

Um lfs-Dateitypen für unser Repository zu konfigurieren, fügen Sie der Datei .gitattributesim Projektstamm einige Zeilen hinzu (möglicherweise müssen Sie sie erstellen, und Windows lässt Sie möglicherweise keine Datei damit im Explorer erstellen).

## 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

Die meisten Dateien, die binär sind und sehr groß sein können, werden hier aufgelistet. Ich werde ein wenig erklären:

Zeilen, die mit # beginnen, sind Kommentare;
filter=lfs diff=lfs merge=lfs- Dies sind magische Wörter, mit denen Git lfs für diese Dateitypen verwendet. -text bedeutet, dass die Datei binär ist und Sie sie nicht zusammenführen müssen.

Wenn Ihr Projekt andere große Binärdateien verwendet, fügen Sie diese später hier hinzu. Das Ändern der Art des Dateispeichers (Übertragen auf lfs oder Entfernen von dort) ist recht schwierig.

Der nächste Schritt besteht darin, zu versuchen, die Situation durch komplexe Zusammenführungen leicht zu verbessern.
Unity enthält das Dienstprogramm UnityYAMLMerge , mit dem Sie Yaml-Dateien effektiv zusammenführen können. Fügen Sie der Datei .gitattributeseinige Zeilen hinzu:

*.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

Lassen Sie mich erklären, was wir getan haben:
Für CS-Dateien wurde vorgeschlagen, dass Text C # -Code sein würde.
für cginc und Shader - Dateien auch wählen sie eine Textdarstellung
für die meisten Unity yaml Dateien, sie einen benutzerdefinierten merge Fahrer wählen unityyamlmerge

Sie auch so konfigurieren müssen: fügen Sie den folgenden Code zu jeder .gitconfig, am einfachsten mit den lokalen einem auf dem .git gelegen / config Pfad aus Repository-Stammverzeichnis:

[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

Das Flag -p zwingt UnityYamlMerge, den Inhalt von Dateien zu ändern, auch wenn der Konflikt nicht vollständig gelöst werden konnte, und vereinfacht die weitere manuelle Lösung erheblich. Wenn Sie beispielsweise zwei Zweige zusammenführen, in denen dieselbe Szene mithilfe des Standard-Git-Zusammenführungsmechanismus geändert wurde, werden viele Änderungen angezeigt. Bei Verwendung eines benutzerdefinierten Treibers enthält der Konflikt genau eine Zeile, auch wenn dasselbe Feld derselben Komponente geändert wurde.

Der Einfachheit halber habe ich ein kleines Skript erstellt, mit dem Unityyamlmerge beim ersten Öffnen eines Projekts durch Unity automatisch installiert werden kann. Es kann an einer beliebigen Stelle im Ordner "Assets" abgelegt werden (es erfordert, dass git auf dem System installiert und in der PATH-Variablen registriert ist, d. H. Mit dem Befehl git zugänglich ist).

diese Klasse
#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 .

endgültige Version von .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


Nach Abschluss dieser Schritte empfehle ich dringend, den aktuellen Status des Repositorys festzuschreiben.

Bereites Projekt https://github.com/newnon/UnityGitHabr1
Ich erinnere Sie erneut daran, dass git korrekt funktioniert. Git muss im System installiert sein und über den Befehl git zugänglich sein.

Wenn Sie experimentieren möchten
github test1 test2 test3
merge test1 test2 test3
test2 test1 test3 m_LocalPosition
E Unity Tools/Git/

All Articles