J'ai un dépôt de 10 Go sur une machine Linux qui est sur NFS. La première fois git status
prend 36 minutes et git status
prend 8 minutes. Il semble que Git dépend du système d'exploitation pour la mise en cache des fichiers. Seules les premières commandes git
comme commit
, status
qui impliquent de compresser/remballer l'ensemble du référentiel prennent très longtemps pour un énorme référentiel. Je ne sais pas si vous avez utilisé git status
sur une telle pension, mais quelqu'un a-t-il rencontré ce problème?
J'ai essayé git gc
, git clean
, git repack
mais le temps pris est toujours/presque le même.
Est-ce que les sous-modules ou d'autres concepts comme la division du dépôt en plus petits seront utiles? Si tel est le cas, quel est le meilleur moyen de fractionner un dépôt plus important. Existe-t-il un autre moyen d'améliorer le temps nécessaire aux commandes git sur un grand dépôt?
Pour être plus précis, git dépend de l'efficacité de l'appel système lstat(2)
, donc peaufiner "timeout cache cache" pourrait faire l'affaire.
Le manuel de git-update-index
- essentiellement un mode manuel pour git-status
- décrit ce que vous pouvez faire pour y remédier, en en utilisant le --assume-unchanged
flag pour supprimer son comportement normal et mettre à jour manuellement les chemins que vous avez modifiés. Vous pouvez même programmer votre éditeur pour désactiver ce drapeau à chaque fois que vous enregistrez un fichier.
L’alternative, comme vous le suggérez, est de réduire la taille de votre paiement (la taille des fichiers de paquets n’entre pas vraiment en jeu ici). Les options sont une caisse creuse, des sous-modules ou l'outil repo de Google.
(Il existe une liste de diffusion discussion sur l'utilisation de Git avec NFS , mais elle ne répond pas à de nombreuses questions.)
Je vois également ce problème sur un grand projet partagé sur NFS.
Il m'a fallu un certain temps pour découvrir l'indicateur - uno qui peut être attribué à la fois à git commit et à git status.
Ce que cet indicateur fait est de désactiver la recherche de fichiers non suivis. Cela réduit considérablement le nombre d'opérations nfs. La raison en est que pour que git puisse découvrir des fichiers non suivis, il doit regarder dans tous les sous-répertoires, donc si vous avez plusieurs sous-répertoires, cela vous blessera. En désactivant git de rechercher des fichiers non suivis, vous éliminez toutes ces opérations NFS.
Combinez cela avec l'indicateur core.preloadindex et vous pouvez obtenir des performances résonnables même sur NFS.
Essayez git gc . Aussi, git clean mai aide.
[~ # ~] mise à jour [~ # ~] - Je ne sais pas d'où vient le vote négatif, mais le manuel de git indique spécifiquement:
Exécute un certain nombre de tâches de gestion interne dans le référentiel actuel, telles que la compression des révisions de fichiers (pour réduire l'espace disque et augmenter les performances) et supprimer les objets inaccessibles qui peuvent avoir été créés à partir d'appels antérieurs de git add.
Les utilisateurs sont encouragés à exécuter cette tâche régulièrement dans chaque référentiel pour maintenir une bonne utilisation de l'espace disque et de bonnes performances de fonctionnement.
Je remarque toujours une différence après avoir exécuté git gc lorsque le statut de git est lent!
MISE À JOUR II - Je ne sais pas comment j'ai raté cela, mais l'OP a déjà essayé git gc et git clean. Je jure que ce n'était pas là à l'origine, mais je ne vois aucun changement dans les modifications. Désolé!
Si votre dépôt git fait un usage intensif des sous-modules, vous pouvez considérablement accélérer les performances de l'état git en modifiant le fichier de configuration dans le répertoire .git et en définissant ignore = dirty
sur tout sous-module particulièrement grand/lourd. Par exemple:
[submodule "mysubmodule"]
url = ssh://mysubmoduleURL
ignore = dirty
Vous perdrez la commodité d'un rappel qu'il y a des changements non programmés dans l'un des sous-modules que vous avez peut-être oublié, mais vous conserverez toujours la commodité principale de savoir quand les sous-modules ne sont pas synchronisés avec le référentiel principal. De plus, vous pouvez toujours changer votre répertoire de travail en sous-module lui-même et utiliser l'état git à l'intérieur comme d'habitude pour voir plus d'informations. Voir cette question pour plus de détails sur ce que signifie "sale".
Les performances du statut git devraient s'améliorer avec Git 2.13 (T2 2017).
Voir commit 950a234 (14 avril 2017) par Jeff Hostetler (jeffhostetler
) .
(Fusionné par Junio C Hamano - gitster
- in commit 8b6bba6 , 24 avr 2017)
string-list
: Utilisez macro ALLOC_GROW
lors de la réaffectation string_list
Utilisez la macro
ALLOC_GROW()
lors de la réaffectation d'un tableaustring_list
Plutôt que de simplement l'augmenter de 32.
Il s'agit d'une optimisation des performances.Lors de l'état sur un référentiel très volumineux et de nombreuses modifications, un pourcentage important du temps d'exécution total est consacré à la réaffectation du
wt_status.changes
Tablea .Ce changement diminue le temps en
wt_status_collect_changes_worktree()
de 125 secondes à 45 secondes sur mon très grand référentiel.
De plus, Git 2.17 (Q2 2018) introduira une nouvelle trace, pour mesurer où le temps est passé dans les opérations lourdes d'index.
Voir commit ca54d9b (27 janvier 2018) par Nguyễn Thái Ngọc Duy (pclouds
) .
(Fusionné par Junio C Hamano - gitster
- in commit 090dbea , 15 février 2018)
trace
: mesure où le temps est passé dans les opérations lourdes d'indexTous les blocs de code lourds connus sont mesurés (sauf l'accès à la base de données d'objets). Cela devrait permettre d'identifier si une optimisation est efficace ou non.
Un statut git non optimisé donnerait quelque chose comme ci-dessous:
0.001791141 s: read cache ...
0.004011363 s: preload index
0.000516161 s: refresh index
0.003139257 s: git command: ... 'status' '--porcelain=2'
0.006788129 s: diff-files
0.002090267 s: diff-index
0.001885735 s: initialize name hash
0.032013138 s: read directory
0.051781209 s: git command: './git' 'status'
Le même Git 2.17 (Q2 2018) améliore git status
Avec:
commit f39a757 , commit 3ca1897 , commit fd9b544 , commit d7d1b49 (09 janvier 2018) par Jeff Hostetler (jeffhostetler
) .
(Fusionné par Junio C Hamano - gitster
- in commit 4094e47 , 08 mars 2018)
"git status
" Peut passer beaucoup de cycles pour calculer la relation entre la branche courante et son amont, qui peut maintenant être désactivé avec l'option "--no-ahead-behind
".
commit ebbed3b (25 février 2018) by Derrick Stolee (derrickstolee
) .
revision.c
: Réduire les requêtes de base de données d'objetsDans
mark_parents_uninteresting()
, nous vérifions l'existence d'un fichier objet pour voir si nous devons traiter un commit comme analysé. Le résultat est de définir le bit "analysé" sur la validation.Modifiez la condition pour vérifier uniquement
has_object_file()
si le résultat changerait le bit analysé.Lorsqu'une branche locale est différente de sa référence amont, "
git status
" Calculera les décomptes avant/arrière.
Ceci utilisePaint_down_to_common()
et frappemark_parents_uninteresting()
.Sur une copie du dépôt Linux avec une instance locale de "master" derrière la branche distante "
Origin/master
" De ~ 60 000 commits, nous constatons que les performances de "git status
" Sont passées de 1,42 seconde à 1,32 seconde, pour une différence relative de -7,0%.
git config --global core.preloadIndex true
A fait le travail pour moi. Consultez la documentation officielle ici .
Dans notre base de code où nous avons quelque part dans la gamme de 20 à 30 sous-modules,git status --ignore-submodules
a accéléré considérablement les choses pour moi. Notez que ceci ne rendra pas compte de l'état des sous-modules.
Je ne sais pas quel sens cela fait, mais pour moi, le statut prenait 30 minutes, j'ai essayé tout ce que je pouvais trouver sur le Web, enfin, j'ai fait git reset
J'ai eu des centaines de changements que j'ai appliqués à partir de stash où le stash a été créé à partir d'une branche différente mais appliqué sur cette branche, ils ont tous été mis en scène mais pas validés (expliquant simplement ce que j'ai fait différemment avant de rencontrer ce problème), git reset
a pris 15 minutes mais après cela, tout a commencé à fonctionner rapidement comme moins d'une seconde pour le statut. Je ne suis pas un expert git qui dit simplement ce qui a résolu mon problème, j'espère que cela aidera les autres qui atterriront sur cette page.
Quelque chose qui n'a pas encore été mentionné est d'activer le cache du système de fichiers sur les machines Windows (les systèmes de fichiers Linux sont complètement différents et git a été optimisé pour eux, donc cela n'aide probablement que sur Windows).
git config core.fscache true
git config core.ignoreStat true
MAIS: Les fichiers modifiés doivent être ajoutés ensuite par le développeur lui-même avec git add
. Git ne trouve pas de changements lui-même.