Unité + git = amitié: partie 1 set de gentleman

image
Le système de contrôle de version de git est depuis longtemps devenu la norme de facto dans le monde du développement, mais pour la plupart des développeurs Unity, ce n'est pas un secret qu'il existe un certain nombre de difficultés associées aux fonctionnalités Unity qui l'empêchent d'être efficacement utilisé avec git.

Voici une liste des problèmes courants:

  1. les fichiers inutiles entrent dans le référentiel ou vice versa n'obtiennent pas les bons
  2. de nombreux fichiers volumineux gonflent la taille du référentiel
  3. problème avec la fusion des fichiers Unity yaml
  4. seul le fichier lui-même ou seule la méta est ajoutée au référentiel
  5. il y a des dossiers vides dans le projet
  6. complexité de la numérotation automatique des versions et des builds
  7. inconvénient d'utiliser du code entre plusieurs projets

Vous pouvez lire la solution à ces problèmes liés à l'utilisation conjointe de git et Unity dans ma série d'articles.

Cet article décrira la solution aux trois premiers problèmes.

Essayons de décrire par étapes les méthodes pour résoudre chacun des problèmes.

La première chose que nous devons faire après avoir créé le référentiel pour votre projet est de configurer les exceptions, je ne m'attarderai pas là-dessus en détail, voici un bon exemple .

La seule remarque est que vous devriez probablement ajouter quelques exceptions à la fin
! *. Dll - car si vous utilisez des plugins ou des actifs tiers, vous devrez stocker la dll dans le référentiel et sous Windows git ignore la dll par défaut;
! *. obj - si vous utilisez des modèles dans ce format, à nouveau dans windows les fichiers obj peuvent être ignorés par défaut

ma version est .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


La deuxième étape, nous allons essayer de résoudre le problème de la croissance du référentiel à partir de fichiers volumineux. Cette solution est LFS

en savoir plus sur LFS
LFS — git, git , key-value .

, git LFS checkout .

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

Pour configurer les types de fichiers lfs pour notre référentiel, ajoutez .gitattributesquelques lignes au fichier à la racine du projet (vous devrez peut-être le créer, et Windows ne vous laissera peut-être pas créer un fichier avec cela dans l'Explorateur)

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

la plupart des fichiers binaires et assez volumineux sont répertoriés ici. Je vais vous expliquer un peu: les

lignes commençant par # sont des commentaires;
filter=lfs diff=lfs merge=lfs- ce sont des mots magiques qui font que git utilise lfs pour ces types de fichiers; -text signifie que le fichier est binaire et que vous n'avez pas besoin de le fusionner.

Si votre projet utilise d'autres gros fichiers binaires, ajoutez-les ici plus tard, changer le type de stockage de fichiers (transférer vers lfs ou le supprimer de là) sera assez difficile.

L'étape suivante consiste à essayer d'améliorer légèrement la situation lors de fusions complexes.
Unity inclut l'utilitaire UnityYAMLMerge , qui vous permet de fusionner efficacement les fichiers yaml. Ajoutez .gitattributesquelques lignes au fichier :

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

Permettez-moi d'expliquer ce que nous avons fait:
pour les fichiers .cs, ils ont suggéré qu'il y aurait du texte en code C #;
pour les fichiers cginc et shader, ils ont également choisi une représentation textuelle
pour la plupart des fichiers yaml Unity, ils ont choisi un pilote de fusion personnalisé unityamlmerge

Vous devez également le configurer: ajoutez le code suivant à n'importe quel .gitconfig, le plus simplement au code local situé sur le chemin .git / config de racine du référentiel:

[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

L'indicateur -p force UnityYamlMerge à modifier le contenu des fichiers même si le conflit n'a pas pu être complètement résolu, et simplifie considérablement sa résolution manuelle. Par exemple, lors de la fusion de deux branches où la même scène a été modifiée, en utilisant le mécanisme de fusion git standard, nous verrons de nombreux changements. Lorsque vous utilisez un pilote personnalisé, même si le même champ du même composant a été modifié, il y aura exactement 1 ligne dans le conflit.

Pour plus de commodité, j'ai créé un petit script qui permettra à l'unitéyamlmerge d'être installé automatiquement la première fois qu'un projet est ouvert par Unity. Il peut être placé n'importe où dans le dossier Assets (il nécessite que git soit installé sur le système et enregistré dans la variable PATH, c'est-à-dire qu'il soit accessible par la commande git);

cette classe
#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 .

version finale de .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


Après avoir terminé ces étapes, je recommande fortement de valider l'état actuel du référentiel.

Projet prêt https://github.com/newnon/UnityGitHabr1
encore une fois je vous rappelle de travailler correctement, git doit être installé dans le système et accessible par la commande git.

Si vous voulez expérimenter
github test1 test2 test3
merge test1 test2 test3
test2 test1 test3 m_LocalPosition
E Unity Tools/Git/

All Articles