Aller au contenu

Git avancé : gros dépôts et sous-projets

Cause Symptôme Remède
Historique très long clone et fetch lents Clone superficiel ou partiel
Gros fichiers binaires versionnés Dépôt de plusieurs Go Git LFS, ne pas versionner
Beaucoup de fichiers git status lent core.fsmonitor, sparse-checkout, maintenance
Beaucoup d’objets libres Opérations lentes git gc, git maintenance

Mesurer d’abord :

Fenêtre de terminal
git count-objects -vH
du -sh .git
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| awk '$1=="blob"{print $3, $4}' | sort -rn | head -10 # les 10 plus gros fichiers de l'historique
Fenêtre de terminal
git clone --depth 1 https://git.exemple.com/depot.git # dernier commit seulement
git clone --depth 50 --branch main https://git.exemple.com/depot.git
git fetch --deepen=100 # approfondir
git fetch --unshallow # récupérer tout l'historique
git clone --depth 1 --single-branch --branch v1.4.0 https://git.exemple.com/depot.git

Idéal pour l’intégration continue et les déploiements : on ne veut que le dernier état. Limites : git log, blame et bisect sont tronqués ; certaines opérations (rebase sur un ancien commit) échouent. Dans Gitea Actions : fetch-depth: 1 (le défaut de actions/checkout) ; fetch-depth: 0 pour l’historique complet (voir Gitea Actions : écrire un workflow).

Fenêtre de terminal
git clone --filter=blob:none https://git.exemple.com/depot.git # sans le contenu des fichiers (téléchargés à la demande)
git clone --filter=tree:0 https://git.exemple.com/depot.git # sans arbres : encore plus léger
git clone --filter=blob:limit=1m https://git.exemple.com/depot.git # sans les fichiers de plus de 1 Mo

L’historique est complet (log, blame fonctionnent) ; le contenu des fichiers est récupéré à la demande, quand on en a besoin (réseau nécessaire). Le serveur doit prendre en charge cette fonction (Gitea, GitHub, GitLab le font en général).

Sparse-checkout : ne récupérer qu’une partie des fichiers

Section intitulée « Sparse-checkout : ne récupérer qu’une partie des fichiers »
Fenêtre de terminal
git clone --filter=blob:none --sparse https://git.exemple.com/monodepot.git
cd monodepot
git sparse-checkout set paquets/api paquets/commun # seuls ces dossiers sont extraits
git sparse-checkout add paquets/web
git sparse-checkout list
git sparse-checkout disable # tout extraire à nouveau

Utile en monodépôt : on travaille sur quelques dossiers parmi des milliers. Combiné au clone partiel, le temps de clonage et l’espace disque chutent fortement.

Un sous-module inclut un autre dépôt Git à un commit précis, dans un sous-dossier.

Fenêtre de terminal
git submodule add https://git.exemple.com/biblio.git vendor/biblio
git commit -m "build: ajouter le sous-module biblio"
git clone --recurse-submodules https://git.exemple.com/projet.git # cloner avec les sous-modules
git submodule update --init --recursive # après un clone simple
git submodule status
git submodule update --remote vendor/biblio # passer à la dernière version de la branche suivie
git submodule foreach 'git switch main && git pull' # commande dans chaque sous-module
git config --global submodule.recurse true # git pull / checkout appliquent aux sous-modules

Fichier .gitmodules (versionné) :

[submodule "vendor/biblio"]
path = vendor/biblio
url = https://git.exemple.com/biblio.git
branch = main
Principe Détail
Le projet principal enregistre un commit précis du sous-module La mise à jour est un commit du projet principal
Modifier le sous-module Entrer dans le dossier, committer et pousser dans son propre dépôt, puis valider le nouveau pointeur dans le projet principal
Supprimer git submodule deinit -f vendor/biblio, git rm -f vendor/biblio, rm -rf .git/modules/vendor/biblio

Pièges : oublier de pousser le sous-module avant le projet principal (les collègues ne trouvent pas le commit), HEAD détaché dans le sous-module, clone sans --recurse-submodules (dossier vide). Les sous-modules conviennent à des dépendances rarement modifiées ; pour des bibliothèques en développement actif, un gestionnaire de paquets (npm, composer, pip) est souvent plus simple (Node.js : npm).

Subtree : intégrer un autre dépôt dans l’historique

Section intitulée « Subtree : intégrer un autre dépôt dans l’historique »
Fenêtre de terminal
git subtree add --prefix=vendor/biblio https://git.exemple.com/biblio.git main --squash
git subtree pull --prefix=vendor/biblio https://git.exemple.com/biblio.git main --squash
git subtree push --prefix=vendor/biblio https://git.exemple.com/biblio.git correctif

Le contenu de l’autre dépôt est copié dans le vôtre (aucun fichier .gitmodules, rien à initialiser pour les collègues). Plus simple pour les utilisateurs, mais l’historique s’alourdit et la contribution en retour est plus délicate.

Sous-module Subtree
Clone par un collègue Étapes supplémentaires Rien de particulier
Contenu dans le dépôt principal Un pointeur Une copie
Historique Séparé Fusionné (ou résumé avec --squash)
Contribuer au projet source Naturel (dépôt distinct) Plus complexe

Git LFS remplace les gros fichiers binaires (images, vidéos, modèles) par de petits pointeurs ; les contenus sont stockés sur un serveur dédié.

Fenêtre de terminal
sudo apt install git-lfs
git lfs install # à faire une fois par utilisateur
git lfs track "*.psd" "*.mp4" "assets/**/*.zip"
git add .gitattributes
git add design.psd
git commit -m "feat: ajouter la maquette"
git lfs ls-files
git lfs pull # récupérer les contenus

.gitattributes :

*.psd filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text

Le serveur doit activer LFS (Gitea : option de configuration [lfs] dans app.ini, voir Gitea : configuration) ; l’espace de stockage est à prévoir dans la sauvegarde (Gitea : sauvegarde et restauration).

Avant d’adopter LFS, se demander s’il faut versionner ces fichiers : des artefacts de build, des dépendances ou des données générées n’ont pas leur place dans Git.

Fenêtre de terminal
git maintenance start # planifie la maintenance en arrière-plan (cron ou minuteur systemd)
git maintenance run # lance les tâches maintenant
git maintenance run --task=gc
git gc --aggressive --prune=now # compactage poussé (long, occasionnel)
git repack -adf --depth=50 --window=250
git config core.fsmonitor true # accélère git status sur de gros dépôts (surveillance de fichiers)
git config core.untrackedCache true
git config feature.manyFiles true # réglages pour les dépôts à très nombreux fichiers

git maintenance start configure des tâches régulières (prélecture, commit-graph, regroupement des paquets, gc léger) qui gardent le dépôt rapide sans intervention.

Voir Sécurité et configuration pour git filter-repo. Après réécriture, tous les clones doivent être refaits, et les anciens objets purgés sur le serveur (git gc --prune=now).

Fenêtre de terminal
git bundle create depot.bundle --all # tout l'historique dans un fichier
git bundle create mises-a-jour.bundle main ^v1.4.0 # seulement les commits depuis une version
git bundle verify depot.bundle
git clone depot.bundle copie-du-depot
git fetch depot.bundle main:refs/remotes/bundle/main

Pratique pour transporter un dépôt sans réseau (clé USB), sauvegarder ou travailler hors ligne.

Fenêtre de terminal
git clone --mirror https://git.exemple.com/depot.git depot.git # copie fidèle (toutes les références)
cd depot.git && git remote update # mise à jour de la copie
tar -czf depot-$(date +%F).tar.gz depot.git

Un clone miroir sauvegarde branches, étiquettes et références ; pour tout le serveur Gitea (dépôts, utilisateurs, tickets), voir Gitea : sauvegarde et restauration.

Symptôme Piste
Le dossier d’un sous-module est vide git submodule update --init --recursive
fatal: remote error: upload-pack: not our ref (sous-module) Commit du sous-module non poussé dans son dépôt
git pull ne met pas à jour les sous-modules git submodule update --init --recursive, ou submodule.recurse true
Clone superficiel : fatal: shallow update not allowed Pousser depuis un clone superficiel vers certains serveurs : approfondir (--unshallow)
LFS : fichiers de quelques octets au lieu du contenu git lfs pull, ou git lfs install non fait
batch response: This repository is over its data quota Quota LFS dépassé sur le serveur
git status très lent core.fsmonitor, maintenance, sparse-checkout, exclure les dossiers volumineux (.gitignore)
Dépôt énorme à cause d’un gros fichier ancien filter-repo ou LFS migrate, puis reclonage

Ubuntu 24.04 et 26.04 : différences à connaître

Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »

Aucune propre à Ubuntu. git-lfs est disponible dans les dépôts des deux versions ; git maintenance et sparse-checkout demandent des versions récentes de Git.