145M = .git/objects/pack/
Я написал скрипт для суммирования размеров различий каждого коммита и коммита перед ним, двигаясь назад от вершины каждой ветви. Получилось 129 МБ, и это без сжатия и без учёта одинаковых файлов в разных ветках и общей истории в ветках.
Git учитывает все эти вещи, поэтому я ожидал бы гораздо меньшего размера репозитория. Так почему же .git такой большой?
Я сделал:
git fsck --full
git gc --prune=today --aggressive
git repack
Чтобы ответить на вопрос о количестве файлов/коммитов, у меня есть 19 веток примерно по 40 файлов в каждой. 287 коммитов, найденных с помощью:
git log --oneline --all|wc -l
Для хранения информации об этом не должно требоваться 10' мегабайт.
Некоторые скрипты, которые я использую:
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
Если вы хотите больше строк, см. Также версию Perl в соседнем ответа: 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
Примечание: второй скрипт предназначен для полного удаления информации из ЖКТ (в том числе вся информация из reflogs). Использовать с осторожностью.
Я недавно вытащил неправильно удаленного репозитория в локальный (в Git дистанционного добавить ... " и " удаленное обновление с Git
). После удаления нежелательных дистанционного Реф, ветки и теги я еще 1,4 ГБ (!) неиспользуемого пространства в моем репозитории. Я был только в состоянии избавиться от этого, скопировав ее с файл клон git:///путь/к/репозиторию. Обратите внимание, что
файл://` делает мир разницы, когда клонирование локального репозитория - только объекты дублируются, а не всю структуру.
Редактировать: здесь'ы Ян's один вкладыш для воссоздания всех филиалах в новый репозиторий:
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 count-objects -v
Это должно дать отчет о том, сколько распакованные объекты есть в вашем репозитории, сколько места они занимают, сколько файлов пакета у вас есть и сколько места они занимают.
В идеале, после репака, вы бы не распакованные объекты и один файл пакета, но это'ы совершенно нормально иметь некоторые объекты, которые еще'т напрямую ссылаться на текущей ветки еще присутствует и распаковали.
Если у вас есть один большой пакет и вы хотите знать, что занимает пространство, то вы можете перечислить объекты, которые составляют пакет вместе с тем, как они хранятся.
git verify-pack -v .git/objects/pack/pack-*.idx
Обратите внимание, что проверка-упаковка
принимает сам индексный файл, а не файл обновления. В этом отдаю отчет каждому объекту в стае, ее истинный размер и его размер в упаковке, а также информация о том, что'ов 'deltified' и если да, происхождение цепь Дельта.
Чтобы увидеть, если есть какие-то unusally крупных объектов в репозитории вы можете сортировать численно выход на третьем или четвертом столбцах (например, | сортировка -k3n
).
От этого выхода вы сможете просматривать содержимое любого объекта, используя команду git в шоу
, хотя это не возможно, чтобы увидеть, где именно в истории коммитов репозитория ссылается на объект. Если вам нужно сделать это, попробуйте что-то из этот вопрос.
Просто FYI, самая главная причина, почему вы можете в конечном итоге с нежелательных объектов, держали вокруг, что Git поддерживает reflog.
В reflog есть, чтобы спасти свою задницу, когда вы случайно удалить ветку master или как-то иначе катастрофически повредить ваш репозиторий.
Самый простой способ исправить это, чтобы обрезать свой reflogs перед сжатием (просто убедитесь, что вы никогда не захотите вернуться к любой из коммитов в reflog).
git gc --prune=now --aggressive
git repack
Это отличается от ЖКТ ГК, сливовый=сегодня в том, что он истекает сразу всю reflog.
Если вы хотите найти, какие файлы занимают пространство в вашем репозитории, выполните
ГИТ проверки-пакета -в .в Git/объекты/пакет/*.в IDx | рода -к 3 -н | хвост -5
Затем, извлечь ссылку на Blob-объект, который занимает больше всего места (в последней строке), и проверьте имя файла, которое занимает так много места
ГИТ Рэв-список --объекты --все | команда grep <ссылка>
Это может быть файл, который вы удалили с ГИТ РМ
, но git помнит это, потому что есть еще ссылки на него, такие как теги, пультов и reflog.
Как только вы знаете, какой файл вы хотите избавиться, я рекомендую использовать Git и забыть-клякса
Это простой в использовании, просто сделать
`ГИТ забыть-блоб файл-чтобы забыть
Это позволит удалить все ссылки из Git, удалить большой двоичный объект из каждого коммита в истории, и запустить сборку мусора, чтобы освободить пространство.
ЖКТ-fatfiles сценарий Ви'ы ответ прекрасный, если вы хотите увидеть размер всех данных, но это's так медленно, что будет непригодным для использования. Я снял 40-Линия ограничивать выходной, и он пытался использовать все мой компьютер'с ОЗУ вместо окончания. Так что я переписал его: это в тысячи раз быстрее, имеет дополнительные функции (опционально), и какие-то странные ошибки была удалена старая версия будет давать неточные подсчеты, если сумма выходного, чтобы видеть общее пространство, используемое файлом.
#!/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];
}
Название этого git-fatfiles.pl и запустить его. Чтобы увидеть дисковое пространство, используемое всеми версиями файла, используйте опцию --сумма
. Чтобы увидеть то же самое, но для файлов в каждой директории, используйте опцию --справочники
. Если вы установите кол::байт::человека на CPAN модуль (запуск с "Номер архива CPAN::байт::человека", у), размеры будут отформатированы: "по-21М /путь/к/файлу.МР4 и".
Вы уверены, что считаете только файлы .pack, а не файлы .idx? Они находятся в том же каталоге, что и файлы .pack, но не содержат никаких данных репозитория (как показывает расширение, это не более чем индексы для соответствующего пакета — на самом деле, если вы знаете правильную команду, вы можете легко воссоздать их из файла pack, и git сам делает это при клонировании, поскольку только файл pack передается по встроенному протоколу git).
В качестве репрезентативного примера я посмотрел на свой локальный клон репозитория linux-2.6:
$ du -c *.pack
505888 total
$ du -c *.idx
34300 total
Что указывает на то, что расширение примерно на 7% должно быть обычным явлением.
Есть также файлы вне objects/
; по моему личному опыту, из них index
и gitk.cache
имеют тенденцию быть самыми большими (в общей сложности 11M в моем клоне репозитория linux-2.6).
Другие объекты git, хранящиеся в .git
, включают деревья, коммиты и теги. Коммиты и теги небольшие, но деревья могут стать большими, особенно если в вашем хранилище очень много маленьких файлов. Сколько у вас файлов и сколько коммитов?
Это может произойти, если вы добавили большой кусок файлов случайно и поставил их, не обязательно совершать их. Это может произойти в "рельсы" приложение при запуске пакета установки --развертывание и потом случайно в Git добавить . тогда вы увидите все файлы, добавленные в соответствии поставщика/пачка
отменить добавление их, но они уже есть в Git истории, так что вам придется применить Ви'ы ответ и изменить
видео/паразит-интро.Авина
продавец/пакет` затем запустить вторую команду, которую он предоставляет.
Вы можете увидеть разницу с `подсчет объектов-в ГИТ, по которым в моем случае перед применением скрипта имел размер пакета: от 52К и после его применения составляет 3,8 тыс.
прежде чем делать фильтр-ветке git & ГИТ ГК необходимо просмотреть теги, которые присутствуют в вашем РЕПО. Любая реальная система, которая имеет автоматическая маркировка для таких вещей, как непрерывная интеграция и развертывание сделает паразитные объекты refrenced эти теги , поэтому ГК не могу удалить их, и вы будете по-прежнему держать интересно, почему размер РЕПО еще очень велик.
Лучший способ избавиться от всех нежелательных вещей, чтобы запустить ЖКТ-фильтр &ампер; с Git GC и затем нажмите мастер к новому голые РЕПО. Новые голые РЕПО будет очищен дерево.