Как удалить не имеющие ссылки блобы от моего мерзавца repo

У меня есть GitHub repo, который имел два ответвления - ведущее устройство и выпуск.

Ответвление выпуска содержало двоичные файлы распределения, которые способствовали очень большому repo размеру (> 250 МБ), таким образом, я решил очистить вещи.

Сначала я удалил удаленное ответвление выпуска, через git push origin :release

Затем я удалил локальное ответвление выпуска. Сначала я попробовал git branch -d release, но мерзавец сказал "ошибку: ответвление 'выпуск' не является предком Вашей текущей ГОЛОВЫ". который верен, таким образом я сделал git branch -D release вынудить это быть удаленным.

Но мой размер репозитория, и локально и на GitHub, был все еще огромен. Таким образом я пробежал обычный список команд мерзавца, как git gc --prune=today --aggressive, без удачи.

Путем следования инструкциям Charles Bailey в ТАК 1029969 я смог получить список SHA1s для самых больших блобов. Я затем использовал сценарий от ТАК 460331 для нахождения блобов..., и самые большие пять не существуют, хотя меньшие блобы найдены, таким образом, я знаю, что сценарий работает.

Я думаю, что эти блоги являются двоичными файлами от ответвления выпуска, и они так или иначе были разбросаны после удаления того ответвления. Что правильный путь состоит в том, чтобы избавиться от них?

112
задан Community 23 May 2017 в 11:47
поделиться

4 ответа

Как упоминалось в , этот SO-ответ , git gc действительно может увеличить размер репо!

См. Также этот поток

Теперь в git есть механизм безопасности, позволяющий не удалять объекты, на которые нет ссылок, сразу при запуске ' git gc '.
По умолчанию объекты, на которые нет ссылок, хранятся в течение 2 недель. Это сделано для того, чтобы вам было легче восстанавливать случайно удаленные ветки или коммиты, или чтобы избежать гонки, когда только что созданный объект, который находится в процессе, но еще не упоминается, может быть удален с помощью ' git gc 'процесс выполняется параллельно.

Таким образом, чтобы дать этот льготный период упакованным, но не имеющим ссылки объектам, процесс переупаковки выталкивает эти объекты без ссылок из пакета в их свободную форму, чтобы их можно было выдержать и в конечном итоге обрезать.
Однако объектов, на которые нет ссылок, обычно не так много. Наличие 404855 объектов, на которые нет ссылок - это довольно много, и отправка этих объектов в первую очередь через клон - это глупо и полная трата пропускной способности сети.

В любом случае ... Чтобы решить вашу проблему, вам просто нужно запустить ' git gc 'с аргументом - prune = now , чтобы отключить этот льготный период и сразу же избавиться от тех объектов, на которые нет ссылок (безопасно, только если в то же время не выполняются никакие другие действия git время, которое должно быть легко обеспечить на рабочей станции).

И BTW, используя ' git gc --aggressive ' с более поздней версией git (или ' git repack -a -f - d --window = 250 --depth = 250 ')

В той же теме упоминается :

 git config pack.deltaCacheSize 1

Это ограничивает размер дельта-кэша одним байтом (фактически отключает его) вместо значения по умолчанию 0, что означает неограниченный. Благодаря этому я могу перепаковать этот репозиторий, используя указанную выше команду git repack в системе x86-64 с 4 ГБ ОЗУ и с использованием 4 потоков (это четырехъядерный процессор). Однако использование резидентной памяти увеличивается почти до 3,3 ГБ.

Если ваша машина поддерживает SMP и у вас недостаточно оперативной памяти, вы можете уменьшить количество потоков до одного:

git config pack.threads 1

Кроме того, вы можете дополнительно ограничить использование памяти с помощью аргумент - окно-память в ' git repack '.
m может перепаковать этот репозиторий с помощью приведенной выше команды git repack в системе x86-64 с 4 ГБ ОЗУ и с использованием 4 потоков (это четырехъядерный процессор). Однако использование резидентной памяти увеличивается почти до 3,3 ГБ.

Если ваша машина поддерживает SMP и у вас недостаточно оперативной памяти, вы можете уменьшить количество потоков до одного:

git config pack.threads 1

Кроме того, вы можете дополнительно ограничить использование памяти с помощью аргумент - окно-память в ' git repack '.
m может перепаковать этот репозиторий с помощью приведенной выше команды git repack в системе x86-64 с 4 ГБ ОЗУ и с использованием 4 потоков (это четырехъядерный процессор). Однако использование резидентной памяти увеличивается почти до 3,3 ГБ.

Если ваша машина поддерживает SMP и у вас недостаточно оперативной памяти, вы можете уменьшить количество потоков до одного:

git config pack.threads 1

Кроме того, вы можете дополнительно ограничить использование памяти с помощью аргумент - окно-память в ' git repack '.
Например, при использовании - window-memory = 128M должна сохраняться разумная верхняя граница дельты. использование памяти поиска, хотя это может привести к менее оптимальному совпадению дельты, если репо содержит много больших файлов.


Что касается ветки фильтра, вы можете рассмотреть (с осторожностью) этот сценарий

#!/bin/bash
set -o errexit

# Author: David Underhill
# Script to permanently delete files/folders from your git repository.  To use 
# it, cd to your repository's root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2

if [ $# -eq 0 ]; then
    exit 0
fi

# make sure we're at the root of git repo
if [ ! -d .git ]; then
    echo "Error: must run this script from the root of a git repository"
    exit 1
fi

# remove all paths passed as arguments from the history of the repo
files=$@
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $files" HEAD

# remove the temporary history git-filter-branch otherwise leaves behind for a long time
rm -rf .git/refs/original/ && git reflog expire --all &&  git gc --aggressive --prune
33
ответ дан 24 November 2019 в 02:45
поделиться

git gc --prune = now или низкий уровень git prune --expire now .

19
ответ дан 24 November 2019 в 02:45
поделиться

Каждый раз, когда ваша ГОЛОВА движется, git отслеживает это в reflog . Если вы удалили коммиты, у вас все еще есть «болтающиеся коммиты», потому что они все еще упоминаются в reflog в течение ~ 30 дней. Это подстраховка при случайном удалении коммитов.

Вы можете использовать команду git reflog для удаления определенных коммитов, переупаковки, и т. д., или просто команду высокого уровня:

git gc --prune=now
12
ответ дан 24 November 2019 в 02:45
поделиться

Попробуйте использовать git-filter-branch - он не удаляет большие двоичные объекты, но может удалять большие файлы, которые вы указали, из всего репо. Для меня это уменьшает размер репо с сотен МБ до 12 МБ.

2
ответ дан 24 November 2019 в 02:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: