Les Forges du Titan
Git LFS, fichiers binaires et jeux vidéo
Au-delà de la Citadelle, dans les montagnes les plus reculées du royaume, se dressent les Forges du Titan, des ateliers gigantesques creusés dans la roche volcanique. Ici, les artisans travaillent des artefacts si massifs qu'aucun parchemin ordinaire ne pourrait les contenir : des armures enchantées, des cartes de mondes entiers, des maquettes de cathédrales en trois dimensions.
Le Maître Forgeron t'accueille d'un grognement. Ses mains sont couvertes de suie et de runes.
« Les chroniques standards sont faites pour du texte - des mots, des incantations, des formules. Mais ici, on travaille des artefacts massifs. Des textures, des modèles 3D, des sons, des animations. Si tu essaies de les archiver comme du texte ordinaire, tes chroniques exploseront en taille et deviendront inutilisables. Il te faut un outil spécial. Il te faut les Forges du Titan. »
Pourquoi les fichiers binaires cassent Git
Pour comprendre le problème, il faut d'abord comprendre comment Git stocke les fichiers en interne.
La compression delta
Quand tu modifies un fichier texte, Git ne stocke pas une copie complète à chaque commit. Il calcule la différence (le delta) entre l'ancienne et la nouvelle version. Si tu changes 3 lignes dans un fichier de 1000 lignes, Git ne stocke que ces 3 lignes modifiées.
Avec un fichier binaire (une image PSD, un modèle 3D, un fichier audio), tout change à chaque modification. Même un changement mineur - déplacer un calque de 1 pixel - peut modifier la totalité du fichier binaire. Git ne peut pas calculer un delta efficace. Résultat : chaque version est stockée en entier.
Les pack files
Git regroupe périodiquement les objets dans des pack files pour économiser de l'espace. Cette compression fonctionne très bien pour le texte, mais est quasi inutile pour les binaires déjà compressés (PNG, ZIP, PSD, etc.).
L'historique qui explose
Imaginons un projet de jeu vidéo :
- Tu as une texture de 50 Mo
- Tu la modifies 10 fois pendant le développement
- Git stocke 10 copies quasi-complètes = 500 Mo pour un seul fichier
- Multiplie par des centaines de textures, modèles, sons...
- Ton dépôt fait plusieurs dizaines de Go en quelques mois
Et le pire : un git clone télécharge tout l'historique. Un nouveau développeur qui rejoint le projet doit télécharger des dizaines de Go avant de pouvoir travailler.
Git LFS - Large File Storage
Git LFS (Large File Storage) est une extension officielle de Git qui résout ce problème. Le principe est simple : au lieu de stocker les gros fichiers dans le dépôt Git, LFS les remplace par de petits fichiers pointeurs et stocke les vrais fichiers sur un serveur séparé.
# Sans LFS : le fichier binaire est DANS le dépôt Git
texture.psd (50 Mo) → stocké dans .git/objects/
# Avec LFS : un pointeur léger dans Git, le vrai fichier ailleurs
texture.psd (134 octets, pointeur) → stocké dans .git/objects/
texture.psd (50 Mo, vrai fichier) → stocké sur le serveur LFS Installation
Bash (Linux / macOS / Git Bash sur Windows) :
# Linux (Debian/Ubuntu)
sudo apt install git-lfs
# Linux (Fedora)
sudo dnf install git-lfs
# macOS
brew install git-lfs
# Initialiser LFS pour ton utilisateur (une seule fois)
git lfs install PowerShell (Windows) :
# Windows (avec winget)
winget install GitHub.GitLFS
# Ou télécharger depuis https://git-lfs.com
# Initialiser LFS pour ton utilisateur (une seule fois)
git lfs install La commande git lfs install configure les hooks Git nécessaires dans ta configuration globale. Tu ne la lances qu'une seule fois par machine.
Tracker des fichiers
Pour dire à LFS quels fichiers gérer, tu utilises git lfs track :
# Tracker toutes les images PSD
git lfs track "*.psd"
# Tracker plusieurs types de fichiers
git lfs track "*.png"
git lfs track "*.jpg"
git lfs track "*.wav"
git lfs track "*.mp3"
git lfs track "*.fbx"
git lfs track "*.blend"
# Tracker un fichier spécifique
git lfs track "assets/huge-map.tga" Chaque appel à git lfs track ajoute une ligne dans le fichier .gitattributes à la racine de ton projet :
# Contenu de .gitattributes après les commandes ci-dessus
*.psd filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
assets/huge-map.tga filter=lfs diff=lfs merge=lfs -text Important : le fichier .gitattributes doit être commité dans le dépôt ! C'est lui qui dit aux autres développeurs quels fichiers sont gérés par LFS. Commite-le en premier, avant d'ajouter les fichiers binaires.
Opérations quotidiennes
Une fois LFS configuré, tu utilises Git normalement. Les commandes git add, git commit, git push et git pull fonctionnent de la même manière - LFS s'occupe de tout en arrière-plan.
# Ajouter et commiter un fichier LFS - rien ne change !
git add assets/texture.psd
git commit -m "Ajouter la texture du héros"
git push
# Voir les fichiers gérés par LFS
git lfs ls-files
# Tirer les fichiers LFS depuis le serveur
git lfs pull
# Pousser les fichiers LFS vers le serveur
git lfs push --all origin
# Récupérer les fichiers LFS sans les checkout
git lfs fetch Vérifier l'état de LFS
# Voir quels patterns sont trackés
git lfs track
# Voir les fichiers LFS dans le dépôt
git lfs ls-files
# Voir l'état détaillé
git lfs status
# Voir les informations d'environnement LFS
git lfs env File Locking - verrouiller les fichiers binaires
Avec du code source, si deux développeurs modifient le même fichier, Git peut souvent fusionner les changements automatiquement. Avec un fichier binaire, c'est impossible. Tu ne peux pas "merger" deux versions d'un fichier PSD ou d'un modèle 3D.
La solution : le file locking. Avant de modifier un fichier binaire, tu le verrouilles. Personne d'autre ne peut le modifier tant que tu ne l'as pas déverrouillé.
# Verrouiller un fichier avant de le modifier
git lfs lock assets/personnage-principal.blend
# Voir les fichiers verrouillés (par toi et les autres)
git lfs locks
# Déverrouiller quand tu as fini
git lfs unlock assets/personnage-principal.blend
# Forcer le déverrouillage (si quelqu'un a oublié)
git lfs unlock assets/personnage-principal.blend --force Bonne pratique : dans une équipe, établis la règle suivante : on ne modifie jamais un fichier binaire sans le verrouiller d'abord. Cela évite les conflits impossibles à résoudre et les heures de travail perdues.
Pour rendre le locking obligatoire sur certains fichiers, ajoute l'attribut lockable dans .gitattributes :
# Rendre le locking obligatoire pour les fichiers Blender
*.blend filter=lfs diff=lfs merge=lfs -text lockable Avec lockable, les fichiers sont automatiquement en lecture seule tant qu'ils ne sont pas verrouillés. Cela empêche les modifications accidentelles.
Intégration avec les moteurs de jeu
Chaque moteur de jeu a ses spécificités. Voici comment configurer Git + LFS pour les trois moteurs les plus populaires.
Unity
Configuration essentielle :
- Asset Serialization : dans Edit > Project Settings > Editor, mets Asset Serialization Mode sur Force Text. Cela permet à Git de faire des diffs sur les fichiers de scènes et prefabs.
- Meta files : active Visible Meta Files. Les fichiers
.metadoivent être commités - ils contiennent les GUIDs qui lient les assets entre eux. (Note : depuis Unity 2020+, ce paramètre est le comportement par défaut et le setting a été supprimé de l'interface. Les meta files sont toujours visibles.)
.gitignore pour Unity :
# .gitignore Unity
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/[Uu]ser[Ss]ettings/
# IDE
.vs/
.vscode/
*.csproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
# Builds
*.apk
*.aab
*.unitypackage
*.app
# Crashlytics
crashlytics-build.properties Patterns LFS recommandés pour Unity :
# Textures et images
git lfs track "*.psd"
git lfs track "*.png"
git lfs track "*.jpg"
git lfs track "*.tga"
git lfs track "*.tif"
git lfs track "*.exr"
git lfs track "*.hdr"
# Audio
git lfs track "*.wav"
git lfs track "*.mp3"
git lfs track "*.ogg"
# Modèles 3D
git lfs track "*.fbx"
git lfs track "*.obj"
git lfs track "*.blend"
# Vidéo
git lfs track "*.mp4"
git lfs track "*.mov"
# Polices
git lfs track "*.ttf"
git lfs track "*.otf"
# Unity spécifique - fichiers volumineux
git lfs track "*.unitypackage"
# Note : *.asset est du YAML texte si Force Text est actif.
# Le LFS est optionnel pour ces fichiers - utile seulement
# s'ils sont très volumineux malgré le format texte. Attention : ne mets PAS les fichiers .unity (scènes) ni les .prefab dans LFS si tu as activé Force Text. Ce sont des fichiers YAML lisibles que Git peut différencier et fusionner. Seuls les vrais binaires vont dans LFS.
Unreal Engine
Unreal utilise des formats binaires propriétaires (.uasset, .umap) pour quasiment tout. C'est un cas où LFS est absolument indispensable.
.gitignore pour Unreal Engine 5 :
# .gitignore Unreal Engine 5
/Binaries/
/DerivedDataCache/
/Intermediate/
/Saved/
/.vs/
/.vscode/
# Build
/Build/
# Compilés
*.VC.db
*.opensdf
*.opendb
*.sdf
*.suo
*.sln.docstates
# Fichiers temporaires
*.tmp
*.log Patterns LFS pour Unreal :
# Assets Unreal (TOUS binaires)
git lfs track "*.uasset"
git lfs track "*.umap"
# Textures et médias (même patterns que Unity)
git lfs track "*.png"
git lfs track "*.jpg"
git lfs track "*.psd"
git lfs track "*.tga"
git lfs track "*.exr"
git lfs track "*.hdr"
git lfs track "*.wav"
git lfs track "*.mp3"
git lfs track "*.mp4"
git lfs track "*.fbx"
git lfs track "*.blend" Godot
Godot est le moteur le plus Git-friendly des trois. La majorité de ses formats sont en texte :
.tscn(scènes) : format texte - Git peut différencier et fusionner.tres(ressources) : format texte.gd(scripts GDScript) : texte pur.gdshader(shaders) : texte pur
Seuls les assets importés (images, sons, modèles) sont binaires.
.gitignore pour Godot :
# .gitignore Godot
/.godot/ # Godot 4 (cache, imports, données éditeur)
/android/
/export/
*.translation
# Import cache Godot 3 (régénéré automatiquement)
# En Godot 4, ce dossier est remplacé par .godot/
.import/ Patterns LFS pour Godot :
# Seuls les vrais binaires ont besoin de LFS avec Godot
# PAS de *.tscn ni *.tres : ce sont des formats texte (S-expression)
# que Git peut différencier et fusionner normalement
git lfs track "*.png"
git lfs track "*.jpg"
git lfs track "*.wav"
git lfs track "*.ogg"
git lfs track "*.mp3"
git lfs track "*.glb" # glTF binaire - va dans LFS
# Note : *.gltf est du JSON texte, seul *.glb (version binaire) va dans LFS
git lfs track "*.fbx"
git lfs track "*.blend"
git lfs track "*.ttf"
git lfs track "*.otf"
# Note : *.svg est du XML texte, pas besoin de LFS Avantage Godot : grâce à ses formats texte natifs, tu as beaucoup moins besoin de LFS qu'avec Unity ou Unreal. Les scènes et ressources peuvent être diffées et mergées normalement avec Git. C'est un vrai atout pour le versionnement.
Migrer un projet existant vers LFS
Tu as un projet existant avec des fichiers binaires déjà commités dans l'historique ? Git LFS fournit un outil de migration pour réécrire l'historique et déplacer les fichiers vers LFS rétroactivement.
Attention : la migration réécrit l'historique Git. Cela signifie que tous les membres de l'équipe devront re-cloner le dépôt après la migration. Préviens tout le monde avant de migrer.
# Voir quels fichiers bénéficieraient de LFS (analyse de l'historique)
git lfs migrate info --everything
# Voir les fichiers les plus volumineux
git lfs migrate info --everything --top=20
# Migrer tous les fichiers PSD de tout l'historique vers LFS
git lfs migrate import --everything --include="*.psd"
# Migrer plusieurs types de fichiers en une seule commande
git lfs migrate import --everything --include="*.psd,*.png,*.wav,*.fbx"
# Migrer uniquement la branche courante
git lfs migrate import --include="*.psd"
# Après la migration, pousser le nouvel historique (force push nécessaire !)
git push --force-with-lease Tu peux aussi faire l'opération inverse - retirer des fichiers de LFS :
# Exporter des fichiers de LFS vers le stockage Git normal
git lfs migrate export --everything --include="*.svg" Alternatives à Git LFS
Git LFS n'est pas la seule solution pour gérer les gros fichiers. Voici deux alternatives notables :
git-annex - stockage flexible
git-annex est un outil plus ancien et plus flexible que Git LFS. Au lieu de stocker les fichiers sur un serveur LFS centralisé, git-annex peut les stocker n'importe où : disque dur externe, serveur SSH, S3, Backblaze, etc.
# Initialiser git-annex dans un dépôt
git annex init "mon-poste"
# Ajouter un fichier à git-annex
git annex add assets/gros-fichier.blend
# Ajouter un remote de stockage (disque externe)
git annex initremote disque-externe type=directory directory=/media/backup/annex
# Copier les fichiers vers le remote
git annex copy --to disque-externe
# Récupérer un fichier
git annex get assets/gros-fichier.blend Avantages : stockage décentralisé, pas besoin de serveur LFS, contrôle fin sur où chaque fichier est stocké. Inconvénients : plus complexe que LFS, moins intégré aux forges (GitHub, GitLab).
DVC - Data Version Control
DVC est conçu pour la data science et le machine learning (on en reparlera en détail dans la Quête A2). Il gère les gros fichiers de données et les modèles ML avec un système de pipelines reproductibles.
# Ajouter un gros dataset à DVC (au lieu de Git)
dvc add data/dataset.csv
# Le fichier est remplacé par un pointeur .dvc
# data/dataset.csv.dvc → commité dans Git
# data/dataset.csv → stocké par DVC (local ou remote) Avantages : pipelines reproductibles, intégré à l'écosystème ML. Inconvénients : pas conçu pour le jeu vidéo ou le design.
| Critère | Git LFS | git-annex | DVC |
|---|---|---|---|
| Cas d'usage | Jeux vidéo, design, binaires | Stockage flexible multi-supports | Data science, ML |
| Intégration forges | Excellente (GitHub, GitLab) | Limitée | Bonne |
| Complexité | Faible | Moyenne à élevée | Moyenne |
| File locking | Oui | Non | Non |
| Stockage | Serveur LFS (forge) | N'importe où | S3, GCS, local, SSH |
Bonnes pratiques pour un repo de jeu vidéo
Organiser un dépôt de jeu vidéo demande de la rigueur. Voici les règles qui ont fait leurs preuves dans l'industrie :
Structure recommandée
mon-jeu/
├── .gitignore # Exclure les fichiers générés
├── .gitattributes # Configuration LFS
├── README.md
├── Assets/ # Ou le dossier racine du moteur
│ ├── Art/
│ │ ├── Textures/ # → LFS
│ │ ├── Models/ # → LFS
│ │ ├── Animations/ # → LFS
│ │ └── UI/ # → LFS (sauf SVG)
│ ├── Audio/
│ │ ├── Music/ # → LFS
│ │ ├── SFX/ # → LFS
│ │ └── Voice/ # → LFS
│ ├── Scripts/ # → Git normal (texte)
│ ├── Scenes/ # → Dépend du moteur
│ └── Prefabs/ # → Dépend du moteur
├── Docs/ # Documentation (texte)
└── Tools/ # Scripts d'outils (texte) Règles d'or
- Configure LFS avant le premier commit binaire. Migrer après coup est possible mais pénible.
- Commite le
.gitattributesen premier. Avant tout fichier binaire. - Verrouille avant de modifier un binaire. Toujours. Sans exception.
- Utilise des branches courtes. Plus une branche vit longtemps, plus les conflits binaires sont probables.
- Communique avec ton équipe. "Je travaille sur le modèle du boss" - une simple annonce peut éviter des heures de conflits.
- Privilégie les formats texte quand c'est possible. SVG au lieu de PNG pour les icônes, YAML au lieu de binaire pour les configs, etc.
- Ne commite pas les fichiers générés. Les builds, les caches, les fichiers temporaires n'ont rien à faire dans le dépôt.
Exercice pratique - Configurer un repo de jeu
Configure un dépôt Git avec LFS pour un projet de jeu vidéo fictif. Tu vas créer la structure, configurer LFS, et simuler un workflow avec des fichiers binaires.
Étape 1 - Créer le dépôt et initialiser LFS
# Créer le projet
mkdir projet-forges-titan
cd projet-forges-titan
git init -b main
# Initialiser LFS
git lfs install # Créer le projet
mkdir projet-forges-titan
cd projet-forges-titan
git init -b main
# Initialiser LFS
git lfs install Étape 2 - Configurer les fichiers à tracker
# Tracker les types de fichiers binaires courants
git lfs track "*.png"
git lfs track "*.jpg"
git lfs track "*.psd"
git lfs track "*.wav"
git lfs track "*.mp3"
git lfs track "*.fbx"
git lfs track "*.blend"
# Vérifier que .gitattributes est bien créé
cat .gitattributes # Tracker les types de fichiers binaires courants
git lfs track "*.png"
git lfs track "*.jpg"
git lfs track "*.psd"
git lfs track "*.wav"
git lfs track "*.mp3"
git lfs track "*.fbx"
git lfs track "*.blend"
# Vérifier que .gitattributes est bien créé
Get-Content .gitattributes Étape 3 - Créer la structure du projet
# Créer l'arborescence
mkdir -p Assets/Art/Textures
mkdir -p Assets/Art/Models
mkdir -p Assets/Audio/Music
mkdir -p Assets/Audio/SFX
mkdir -p Assets/Scripts
mkdir -p Docs
# Créer un .gitignore
cat > .gitignore << 'EOF'
# Builds
/Build/
/Builds/
# IDE
.vs/
.vscode/
*.suo
*.user
# OS
.DS_Store
Thumbs.db
# Temporaire
*.tmp
*.log
EOF
# Créer un README
echo "# Mon Projet de Jeu - Les Forges du Titan" > README.md # Créer l'arborescence
New-Item -ItemType Directory -Force -Path Assets/Art/Textures
New-Item -ItemType Directory -Force -Path Assets/Art/Models
New-Item -ItemType Directory -Force -Path Assets/Audio/Music
New-Item -ItemType Directory -Force -Path Assets/Audio/SFX
New-Item -ItemType Directory -Force -Path Assets/Scripts
New-Item -ItemType Directory -Force -Path Docs
# Créer un .gitignore
@"
# Builds
/Build/
/Builds/
# IDE
.vs/
.vscode/
*.suo
*.user
# OS
.DS_Store
Thumbs.db
# Temporaire
*.tmp
*.log
"@ | Set-Content .gitignore
# Créer un README
"# Mon Projet de Jeu - Les Forges du Titan" | Set-Content README.md Étape 4 - Premier commit (configuration)
# Commiter la configuration en premier
git add .gitattributes .gitignore README.md
git commit -m "Initialiser le projet avec LFS et .gitignore" # Commiter la configuration en premier
git add .gitattributes .gitignore README.md
git commit -m "Initialiser le projet avec LFS et .gitignore" Étape 5 - Simuler des fichiers binaires
# Créer des fichiers "binaires" simulés
dd if=/dev/urandom of=Assets/Art/Textures/hero.png bs=1024 count=100 2>/dev/null
dd if=/dev/urandom of=Assets/Audio/SFX/sword.wav bs=1024 count=50 2>/dev/null
# Ajouter un script (fichier texte normal, pas LFS)
cat > Assets/Scripts/player.gd << 'EOF'
extends CharacterBody2D
var speed = 200.0
func _physics_process(delta):
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_right"):
velocity.x += 1
if Input.is_action_pressed("ui_left"):
velocity.x -= 1
velocity = velocity.normalized() * speed
move_and_slide()
EOF
# Commiter
git add .
git commit -m "Ajouter les premiers assets et le script du joueur"
# Vérifier que LFS gère bien les fichiers binaires
git lfs ls-files # Créer des fichiers "binaires" simulés
$bytes = New-Object byte[] 102400
(New-Object Random).NextBytes($bytes)
[IO.File]::WriteAllBytes("Assets/Art/Textures/hero.png", $bytes)
$bytes = New-Object byte[] 51200
(New-Object Random).NextBytes($bytes)
[IO.File]::WriteAllBytes("Assets/Audio/SFX/sword.wav", $bytes)
# Ajouter un script (fichier texte normal, pas LFS)
@"
extends CharacterBody2D
var speed = 200.0
func _physics_process(delta):
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_right"):
velocity.x += 1
if Input.is_action_pressed("ui_left"):
velocity.x -= 1
velocity = velocity.normalized() * speed
move_and_slide()
"@ | Set-Content Assets/Scripts/player.gd
# Commiter
git add .
git commit -m "Ajouter les premiers assets et le script du joueur"
# Vérifier que LFS gère bien les fichiers binaires
git lfs ls-files Étape 6 - Vérifier le résultat
# Les fichiers LFS doivent apparaître ici
git lfs ls-files
# Le script ne doit PAS apparaître (c'est du texte, pas du LFS)
# Tu devrais voir hero.png et sword.wav
# Voir les patterns trackés
git lfs track Récapitulatif des commandes
| Commande | Description |
|---|---|
| git lfs install | Initialiser LFS (une fois par machine) |
| git lfs track "*.ext" | Tracker un type de fichier avec LFS |
| git lfs untrack "*.ext" | Arrêter de tracker un type de fichier |
| git lfs ls-files | Lister les fichiers gérés par LFS |
| git lfs status | Voir l'état des fichiers LFS |
| git lfs pull | Télécharger les fichiers LFS |
| git lfs push --all origin | Pousser tous les fichiers LFS |
| git lfs fetch | Récupérer les fichiers LFS sans checkout |
| git lfs lock <fichier> | Verrouiller un fichier binaire |
| git lfs unlock <fichier> | Déverrouiller un fichier binaire |
| git lfs locks | Lister les fichiers verrouillés |
| git lfs migrate info | Analyser le dépôt pour la migration |
| git lfs migrate import | Migrer des fichiers existants vers LFS |
| git lfs env | Voir la configuration LFS |
Le Maître Forgeron hoche lentement la tête, satisfait.
« Tu vois maintenant pourquoi ces Forges existent. Les artefacts massifs - textures, modèles, sons - ne peuvent pas être traités comme de simples parchemins. Ils ont besoin de leur propre système de stockage, de leur propre discipline. »
« LFS est ton marteau de forgeron. Le file locking est ta discipline. Et le .gitattributes est ton plan de forge. Avec ces trois outils, tu peux versionner n'importe quel projet, même les plus titanesques. »
Il retourne à son enclume, le bruit du marteau résonnant dans les montagnes.
« Maintenant, va forger tes propres artefacts. Et n'oublie jamais : commite le .gitattributes en premier. Toujours. »