Git avancé : gros dépôts et sous-projets
Dépôts volumineux : où est le coût ?
Section intitulée « Dépôts volumineux : où est le coût ? »| 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 :
git count-objects -vHdu -sh .gitgit 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'historiqueClone superficiel (shallow)
Section intitulée « Clone superficiel (shallow) »git clone --depth 1 https://git.exemple.com/depot.git # dernier commit seulementgit clone --depth 50 --branch main https://git.exemple.com/depot.gitgit fetch --deepen=100 # approfondirgit fetch --unshallow # récupérer tout l'historiquegit clone --depth 1 --single-branch --branch v1.4.0 https://git.exemple.com/depot.gitIdé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).
Clone partiel (partial clone)
Section intitulée « Clone partiel (partial clone) »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égergit clone --filter=blob:limit=1m https://git.exemple.com/depot.git # sans les fichiers de plus de 1 MoL’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 »git clone --filter=blob:none --sparse https://git.exemple.com/monodepot.gitcd monodepotgit sparse-checkout set paquets/api paquets/commun # seuls ces dossiers sont extraitsgit sparse-checkout add paquets/webgit sparse-checkout listgit sparse-checkout disable # tout extraire à nouveauUtile 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.
Sous-modules
Section intitulée « Sous-modules »Un sous-module inclut un autre dépôt Git à un commit précis, dans un sous-dossier.
git submodule add https://git.exemple.com/biblio.git vendor/bibliogit commit -m "build: ajouter le sous-module biblio"
git clone --recurse-submodules https://git.exemple.com/projet.git # cloner avec les sous-modulesgit submodule update --init --recursive # après un clone simplegit submodule statusgit submodule update --remote vendor/biblio # passer à la dernière version de la branche suiviegit submodule foreach 'git switch main && git pull' # commande dans chaque sous-modulegit config --global submodule.recurse true # git pull / checkout appliquent aux sous-modulesFichier .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 »git subtree add --prefix=vendor/biblio https://git.exemple.com/biblio.git main --squashgit subtree pull --prefix=vendor/biblio https://git.exemple.com/biblio.git main --squashgit subtree push --prefix=vendor/biblio https://git.exemple.com/biblio.git correctifLe 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 : les gros fichiers
Section intitulée « Git LFS : les gros fichiers »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é.
sudo apt install git-lfsgit lfs install # à faire une fois par utilisateurgit lfs track "*.psd" "*.mp4" "assets/**/*.zip"git add .gitattributesgit add design.psdgit commit -m "feat: ajouter la maquette"git lfs ls-filesgit lfs pull # récupérer les contenus.gitattributes :
*.psd filter=lfs diff=lfs merge=lfs -text*.mp4 filter=lfs diff=lfs merge=lfs -textLe 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.
Maintenance
Section intitulée « Maintenance »git maintenance start # planifie la maintenance en arrière-plan (cron ou minuteur systemd)git maintenance run # lance les tâches maintenantgit maintenance run --task=gcgit gc --aggressive --prune=now # compactage poussé (long, occasionnel)git repack -adf --depth=50 --window=250git config core.fsmonitor true # accélère git status sur de gros dépôts (surveillance de fichiers)git config core.untrackedCache truegit config feature.manyFiles true # réglages pour les dépôts à très nombreux fichiersgit 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.
Retirer de gros fichiers de l’historique
Section intitulée « Retirer de gros fichiers de l’historique »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).
Bundle : un dépôt dans un fichier
Section intitulée « Bundle : un dépôt dans un fichier »git bundle create depot.bundle --all # tout l'historique dans un fichiergit bundle create mises-a-jour.bundle main ^v1.4.0 # seulement les commits depuis une versiongit bundle verify depot.bundlegit clone depot.bundle copie-du-depotgit fetch depot.bundle main:refs/remotes/bundle/mainPratique pour transporter un dépôt sans réseau (clé USB), sauvegarder ou travailler hors ligne.
Sauvegarder un dépôt
Section intitulée « Sauvegarder un dépôt »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 copietar -czf depot-$(date +%F).tar.gz depot.gitUn clone miroir sauvegarde branches, étiquettes et références ; pour tout le serveur Gitea (dépôts, utilisateurs, tickets), voir Gitea : sauvegarde et restauration.
Dépannage
Section intitulée « Dépannage »| 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.