145M = .git/obiecte/pachet/
Am scris un script pentru a adăuga până la dimensiuni de diferențele dintre fiecare a comis și comite înainte de a merge înapoi de la vârful fiecărei ramuri. Am 129MB, care este, fără compresie și fără contabile pentru aceleași fișiere pe ramuri și istorie comună printre ramuri.
Git nevoie de toate aceste lucruri în considerare, astfel încât m-aș aștepta mult, mult mai mic depozit. Deci, de ce este .git atât de mare?
Am'am făcut:
git fsck --full
git gc --prune=today --aggressive
git repack
Să răspundă cu privire la cât de multe fișiere/se angajează, am 19 sucursale aproximativ 40 de fișiere în fiecare. 287 se angajează, găsite cu ajutorul:
git log --oneline --all|wc -l
Acesta nu ar trebui să fie luați 10's de megabytes de spațiu pentru a stoca informații despre acest lucru.
Unele script-uri eu folosesc:
git rev-list --all --objects | \
sed -n $(git rev-list --objects --all | \
cut -f1 -d' ' | \
git cat-file --batch-check | \
grep blob | \
sort -n -k 3 | \
tail -n40 | \
while read hash type size; do
echo -n "-e s/$hash/$size/p ";
done) | \
sort -n -k1
...
89076 images/screenshots/properties.png
103472 images/screenshots/signals.png
9434202 video/parasite-intro.avi
Dacă doriți mai multe linii, a se vedea, de asemenea, versiunea Perl într-un învecinate răspuns: https://stackoverflow.com/a/45366030/266720
git filter-branch -f --index-filter \
'git rm --force --cached --ignore-unmatch video/parasite-intro.avi' \
-- --all
rm -Rf .git/refs/original && \
git reflog expire --expire=now --all && \
git gc --aggressive && \
git prune
Notă: cel de-al doilea scenariu este conceput pentru a elimina informații de la Git complet (inclusiv toate informatiile de la reflogs). Utilizați cu prudență.
Recent am scos alt depozit la distanță în cea locală (git remote add ... " și " git actualizare de la distanță
). După ștergerea nedorite de la distanță ref, ramuri și tag-uri am avut încă 1,4 GB (!) de spațiu irosit în depozit. Am fost doar posibilitatea de a scapa de aceasta prin clonare cu git clona file:///calea/catre/depozit
. Rețineți că file://
face o lume de diferență atunci când clonarea unui depozit local - numai obiecte referite sunt copiate peste, nu toata structura de directoare.
Edit: Aici's Ian's o linie pentru a recrea toate ramurile în noul repo:
d1=#original repo
d2=#new repo (must already exist)
cd $d1
for b in $(git branch | cut -c 3-)
do
git checkout $b
x=$(git rev-parse HEAD)
cd $d2
git checkout -b $b $x
cd $d1
done
git gc
deja are o git repack
astfel încât nu există nici un sens în manual reambalare dacă aveți de gând să fie de a trece unele opțiuni speciale pentru asta.
Primul pas este de a vedea dacă majoritatea spațiului este (așa cum ar fi normal) obiect bază de date.
git count-objects -v
Acest lucru ar trebui să dea un raport de cât de multe despachetat obiecte există în repository-ul dvs., cât de mult spațiu pe care le iau, de câte pachet de fișiere aveți și cât de mult spațiu pe care le iau.
În mod ideal, după un repack, te-ar avea nici despachetat obiecte și un pachet de fișiere, dar's perfect normal sa ai unele obiecte care nu sunt't direct de referință de curent ramuri încă prezente și despachetat.
Dacă aveți un singur pachet mare și vrei să știi ce este de a lua spațiu atunci puteți lista de obiecte care alcătuiesc pachet, împreună cu modul în care acestea sunt stocate.
git verify-pack -v .git/objects/pack/pack-*.idx
Notă: verificați dacă pachetul are un fișier index și nu la pachet fișierul în sine. Acest lucru da un raport de fiecare obiect din pachet, adevărata sa dimensiune și ambalate dimensiune, precum și informații cu privire la dacă-l'a fost 'deltified' și dacă este așa originea delta lanț.
Pentru a vedea dacă există orice neobișnuit de mare de obiecte în depozit dumneavoastră puteți sorta de ieșire numeric pe cea de-a treia celei de-a patra coloane (de exemplu | sort-k3n
).
De la această ieșire va fi capabil pentru a vedea conținutul de orice obiect, folosind `git show comandă, deși nu este posibil pentru a vedea exact unde se angajeze istoria depozit obiect se face referire. Dacă aveți nevoie pentru a face acest lucru, încercați ceva din această întrebare.
Doar ca să știi, cel mai mare motiv de ce s-ar putea termina cu obiecte nedorite fiind menținut în jurul valorii de este că git menține o reflog.
La reflog este acolo pentru a salva fundul, atunci când ștergeți accidental stăpânul tău ramură sau cumva altfel catastrofal deteriora depozit.
Cel mai simplu mod de a rezolva acest lucru este de a trunchia ta reflogs înainte de comprimare (doar asigurați-vă că nu vrei să te întorci la orice se angajează în reflog).
git gc --prune=now --aggressive
git repack
Acest lucru este diferit de `git gc --prune=de astăzi în care expiră în întreaga reflog imediat.
Dacă vrei să găsești ce fișiere sunt inițierea spațiu în depozit git, rula
git verifica-pack -v .git/obiecte/pachet/*.idx | sort-k 3 -n | coada -5
Apoi, extract de blob de referință, care ocupă cel mai mult spațiu (ultima linie), și verificați numele fișierului care este de a lua atât de mult spațiu
git rev-lista de obiecte-toate | grep <referință>
Acest lucru ar putea fi chiar un fișier pe care ați eliminat cu `git rm, dar git își amintește pentru că încă există referiri la aceasta, cum ar fi tag-uri, telecomenzi și reflog.
Odată ce știi ce fișierul pe care doriți să scapi de, am recomandăm să utilizați git uita-blob
Este ușor de utilizat, doar o fac
`git uita-blob fișier-pentru-a uita
Acest lucru va elimina orice referire la git, scoateți pata de fiecare comite în istorie, și a alerga de colectare a gunoiului pentru a elibera spațiu.
Git-fatfiles script-ul de Vi's răspunsul este minunat dacă doriți să vedeți dimensiunea de toate blobs dvs., dar's atât de încet ca să fie inutilizabile. Am scos 40-ieșire linie limită, și a încercat să folosească toate computerul meu's RAM în loc de finisare. Asa ca am rescris-o: aceasta este de mii de ori mai rapid, a adăugat caracteristici (opțional), și unele bug ciudat a fost eliminat--versiunea veche ar da inexacte contează dacă suma ieșire pentru a vedea spațiul total utilizat de către un fișier.
#!/usr/bin/perl
use warnings;
use strict;
use IPC::Open2;
use v5.14;
# Try to get the "format_bytes" function:
my $canFormat = eval {
require Number::Bytes::Human;
Number::Bytes::Human->import('format_bytes');
1;
};
my $format_bytes;
if ($canFormat) {
$format_bytes = \&format_bytes;
}
else {
$format_bytes = sub { return shift; };
}
# parse arguments:
my ($directories, $sum);
{
my $arg = $ARGV[0] // "";
if ($arg eq "--sum" || $arg eq "-s") {
$sum = 1;
}
elsif ($arg eq "--directories" || $arg eq "-d") {
$directories = 1;
$sum = 1;
}
elsif ($arg) {
print "Usage: $0 [ --sum, -s | --directories, -d ]\n";
exit 1;
}
}
# the format is [hash, file]
my %revList = map { (split(' ', $_))[0 => 1]; } qx(git rev-list --all --objects);
my $pid = open2(my $childOut, my $childIn, "git cat-file --batch-check");
# The format is (hash => size)
my %hashSizes = map {
print $childIn $_ . "\n";
my @blobData = split(' ', <$childOut>);
if ($blobData[1] eq 'blob') {
# [hash, size]
$blobData[0] => $blobData[2];
}
else {
();
}
} keys %revList;
close($childIn);
waitpid($pid, 0);
# Need to filter because some aren't files--there are useless directories in this list.
# Format is name => size.
my %fileSizes =
map { exists($hashSizes{$_}) ? ($revList{$_} => $hashSizes{$_}) : () } keys %revList;
my @sortedSizes;
if ($sum) {
my %fileSizeSums;
if ($directories) {
while (my ($name, $size) = each %fileSizes) {
# strip off the trailing part of the filename:
$fileSizeSums{$name =~ s|/[^/]*$||r} += $size;
}
}
else {
while (my ($name, $size) = each %fileSizes) {
$fileSizeSums{$name} += $size;
}
}
@sortedSizes = map { [$_, $fileSizeSums{$_}] }
sort { $fileSizeSums{$a} <=> $fileSizeSums{$b} } keys %fileSizeSums;
}
else {
# Print the space taken by each file/blob, sorted by size
@sortedSizes = map { [$_, $fileSizes{$_}] }
sort { $fileSizes{$a} <=> $fileSizes{$b} } keys %fileSizes;
}
for my $fileSize (@sortedSizes) {
printf "%s\t%s\n", $format_bytes->($fileSize->[1]), $fileSize->[0];
}
Numele asta git-fatfiles.pl și a alerga it. Pentru a vedea spațiul de pe disc utilizat de către toate revizuirile de un fișier, utilizați --sum
opțiune. Pentru a vedea același lucru, dar pentru fișiere în fiecare director, utilizați --directoare
opțiune. Dacă instalați Numărul::Bytes::Uman module cpan (run "cpan Numărul::Bytes::Uman"), dimensiunile vor fi formatat: "21M /path/to/file.mp4".
Ești sigur că se bazează doar .pachet de fișiere și nu .idx fișiere? Ele sunt în același director ca și fișierul .pachet de fișiere, dar nu au nici de depozit de date (ca prelungire indică, ele nu sunt nimic mai mult decât indicii pentru corespunzătoare pack — în fapt, dacă știi comanda corectă, puteți cu ușurință le recrea din pachetul de fișier, și git nu atunci când clonarea, ca doar un pachet de fișier este transferat folosind nativ git protocol).
Ca un eșantion reprezentativ, am luat o privire la meu locale clona a linux-2.6 depozit:
$ du -c *.pack
505888 total
$ du -c *.idx
34300 total
Ceea ce indică o expansiune de aproximativ 7% ar trebui să fie comune.
Există, de asemenea, fișiere în afara obiectelor/; în experiența mea personală, de a le
index " și " gitk.cache` tind să fie cele mai mari (în valoare totală de 11M in clona mea de linux-2.6 depozitul).
Alte git obiecte stocate în .git
includ copaci, se angajează, și tag-uri. Se angajează și tag-uri sunt mici, dar copacii pot obține de mare, în special dacă aveți un număr foarte mare de fișiere mici în depozit. Cât de multe fișiere și cât de multe se angajează ai?
Acest lucru se poate întâmpla dacă ați adăugat o bucată mare de fișiere accidental și pus în scenă de ei, nu neapărat le comit. Acest lucru se poate întâmpla într-o "șine" app atunci când tu a alerga pachet instala --desfășurarea și apoi accidental
git add . atunci veți vedea toate fișierele adăugate în furnizor/pachet
ai unstage ei, dar au ajuns deja in git istorie, deci va trebui să se aplice Vi's a răspunde și de a schimba video/parazitii-intro.avi " cu " furnizor/pachet
apoi atunci a alerga de-a doua comandă el oferă.
Puteți vedea diferența cu git conta-obiecte -v
, care în cazul meu înainte de a aplica scenariul a avut o dimensiune pachet: de 52K și după aplicarea acesteia a fost de 3,8 K.
înainte de a face git filtru-sucursala & git gc tu ar trebui să revizuiască tag-uri care sunt prezente în repo-ul. Orice sistem real, care are etichetare automată pentru lucruri cum ar fi integrarea continuă și implementări va face unwated obiecte încă refrenced de aceste tag-uri , prin urmare gc cant scoateți-le și veți păstra încă vă întrebați de ce dimensiunea repo este încă atât de mare.
Cel mai bun mod de a scăpa de toate ne-a vrut lucruri este de a rula git-filtru & git gc și apoi împingeți-master pentru un nou gol repo. Noul goale repo va avea curățat copac.
Acesta este în valoare de verificarea stacktrace.jurnal. Acesta este de fapt un jurnal de eroare pentru contur se angajează că nu a reușit. Am'am aflat de curand ca-mi stacktrace.jurnalul este de 65,5 GB și aplicația mea este de 66,7 GB.