После удаления двоичного файла из истории Git почему мой репозиторий по-прежнему большой?

Итак, позвольте мне предисловие к этому вопросу, сказав, что мне известны предыдущие вопросы, относящиеся к теме в Stackoverflow. Фактически я пробовал все решения, которые мог найти, но в моем репо есть двоичный файл, который просто отказывается удаляться и продолжает сильно раздувать мой размер репо.

Методы, которые я пробовал,

Оба из них были рекомендованы Darhuuk ответом на Удалить файлы из git repo полностью

Однако после попытки обоих этих решений script, чтобы найти большие файлы в git, все равно находит двоичный код. Однако script from этот ответ больше не находит фиксацию для двоичного файла. Оба этих сценария были предложены этим ответом.

Репо по-прежнему составляет 44 мб после попыток удаления, что слишком велико для относительного небольшого размера источника. Какие предложения большой файл script выполняет эту работу должным образом. Я попытался подтолкнуть к github (я на всякий случай сделал вилку), а затем сделал новый клон, чтобы посмотреть, уменьшился ли размер репо, но он все тот же размер.

Может кто-нибудь объяснить, что я делаю неправильно, или предложить альтернативный метод?

Я должен отметить, что мне не просто интересно обрезать файл из моего локального репо, я также хочу иметь возможность исправить удаленное репо на Github.

Ответы

Ответ 1

2017 Редактирование: вам следует, вероятно, изучить BFG Repo-Cleaner, если вы читаете это.


Так смущающе, почему мои локальные репозитории не уменьшались по размеру, потому что я использовал неправильный путь к файлу в ветки фильтра. Поэтому, когда я благодарю J-16 SDiZ и CodeGnome за ответы, моя проблема была между стулом и клавиатурой.

Чтобы сделать этот вопрос менее памятным для моей глупости и действительно полезным для людей, я потратил время, чтобы написать шаги, которые нужно было бы пройти после обрезки репо, чтобы вернуть репо на Гитубе. Надеюсь, это поможет кому-то выйти из строя.


Удаление поврежденных файлов

Чтобы удалить повреждающие файлы, запустите оболочку script ниже, на основе Github удалит важные данные

#!/usr/bin/env bash
git filter-branch --index-filter 'git rm -r -q --cached --ignore-unmatch '$1'' --prune-empty --tag-name-filter cat -- --all

rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now

Я прошел через каждую ветку в моем локальном репозитории и сделал это, но я честно не уверен, что это необходимо, (вам не нужно делать это на каждой ветке) нужно, чтобы каждая ветвь была локальной для следующего шага, поэтому имейте это в виду. После того, как вы закончите, вы увидите уменьшение размера своего локального репо. Вы также должны иметь возможность запускать blob script в ответе CodeGnome и видеть, что удаление blob удаляется. Если вы не дважды проверяете имя файла и путь и убедитесь, что они верны.

Что git filter-branch фактически выполняет здесь команду, указанную в кавычках, при каждом фиксации в репо.

Остальная часть script просто очищает любую кэшированную версию старых данных.

Нажатие обрезанного репо

Теперь, когда локальное репо находится в состоянии, вам нужно, чтобы это было трюком, чтобы вернуть его на Github. К сожалению, насколько я могу судить, нет возможности полностью удалить двоичные данные из репозитория Github, вот цитата из Github конфиденциальные данные howto

Будь предупрежден, что принудительное нажатие не стирает фиксацию на удаленном репо, оно просто вводит новые и перемещает указатель ветки, чтобы указать на них. Если вы беспокоитесь о том, что пользователи получают доступ к плохим коммитам напрямую через SHA1, вам придется удалить репо и воссоздать его.

Это отстой, что вам нужно воссоздать репозиторий Github, но хорошие новости о том, что воссоздание репо на самом деле довольно просто. Боль в том, что вам также нужно воссоздать данные в проблемах и вики, о которых я расскажу ниже.

Я рекомендую создать новое репо в github, а затем выключить его с помощью своего старого репо, когда вы будете готовы. Это можно сделать, переименовав старый в нечто вроде "имя репо старого", а затем изменив имя вновь созданного репо на "имя репо". Убедитесь, что при создании нового репо для отмены инициализации с помощью README, иначе вы не будете иметь дело с чистым списком.

Если вы завершили последний шаг, вы должны очистить свой репо и готово к работе. Теперь пульты теперь должны быть изменены в соответствии с новым местоположением репозитория Github. Я делаю это, редактируя файл .git/config напрямую, хотя я уверен, что кто-то скажет мне, что это неправильный способ сделать это.

Перед тем, как сделать push, убедитесь, что у вас есть все ветки и теги, которые вы хотите активировать в своем локальном репо. После того, как вы будете готовы нажимать все ветки, используя следующие

git push --all
git push --tags

Теперь вам нужно иметь удаленное репо, чтобы соответствовать вашему обрезанному местному репо. Дважды проверьте, что все данные сделаны на всякий случай.

Теперь, если вам не нужно беспокоиться о проблемах или вики, вы готовы. Если вы читаете дальше.

Перемещение по wikis

Вики Github - это еще одно репо, связанное с вашим основным репо. Итак, чтобы начать клонировать свою старую вики-репо где-то. Затем следующая часть выглядит довольно сложно, насколько я могу судить, вам нужно щелкнуть на вкладке wiki вашего нового репо, чтобы создать вики, но она засекает вновь созданный вики с исходным файлом. Итак, что я сделал, и я не уверен, есть ли лучший способ, это изменить пульт на новое создание вики-репо и сделать толчок к новому местоположению, используя

git push --all --force

Сила нужна здесь, потому что иначе git будет жаловаться на то, что вершина текущей ветки не соответствует. Я думаю, что это может оставить исходную страницу в отдельном состоянии в репозитории git, но эффект от размера репо должен быть незначительным.

Перемещение проблем

Существует совет по этому вопросу, представленный этим ответом. Но глядя на script, связанный в ответ, похоже, что он довольно неполный, есть TODO для импорта комментариев, и я не мог" t скажите, будет ли это приводить к состоянию проблем или нет.

Поэтому, учитывая, что у меня была довольно небольшая очередь открытых проблем, и что я не против потерять закрытые проблемы, я решил перевести вещи вручную. Обратите внимание, что это невозможно сделать с надлежащей атрибуцией других людей в комментариях. Поэтому я думаю, что для более крупного проекта вам нужно будет написать более надежный script, чтобы все было переделано, но это не было необходимо для моего конкретного случая.

Ответ 2

Предполагая, что вы уже удалили blob из своей истории с помощью git -filter-branch (1) и друзей, Git часто хранит вещи в файлах reflogs, packfiles и свободных репозиториях. Заклинание для удаления этих объектов без ссылок:

git prune --expire=now
git reflog expire --expire-unreachable=now --rewrite --all
git repack -a -d
git prune-packed

Если вы это сделали, и у вас все еще есть более крупный репозиторий, чем вы думаете, вам следует, но у вас все еще есть ссылки на ваш блоб где-то в репозитории. Вам нужно вернуться к первому шагу и удалить их. Это может помочь:

# List all blobs by size in bytes.
git rev-list --all --objects   |
    awk '{print $1}'           |
    git cat-file --batch-check |
    fgrep blob                 |
    sort -k3nr

Ответ 3

script в script, чтобы найти большие файлы в git, проверьте файл .pack - то есть, хранилище исходного объекта. Второй script показывает, что большой объект больше не ссылается. Если вы действительно хотите очистить это, вы можете сделать gc и repack:

git gc --aggressive --prune=now
git repack -A -d

Если это все еще не помогает, у вас может быть ссылка на объект в удаленной ветке, вы можете попробовать

  1. Узнайте, какой фиксатор имеет этот объект, см. Какой фиксатор имеет этот blob? и do git branch -a --contains <commit-ish>
  2. Удалите удаленную ветку с помощью git branch -r -D branchname

Обновление - что такое "удаленная ветвь"?

  • Удаленная ветвь - это то, что git fetch, когда вы делаете git fetch/git pull. (git pull совпадает с git fetch refspec + git merge remote-branch.

  • Если вы клонируете удаленный репозиторий, удаление удаленной ветки не должно иметь никакого плохого эффекта - вы всегда можете извлечь/вытащить из пульта снова, используя что-то вроде git fetch origin refs/heads/master:refs/remotes/origin/master (это вытащите ветвь master из удаленный от удаленной ветки remotes/origin/master).

  • Если эта ветка была создана вами, удаление тоже должно быть в порядке - потому что для этого вы должны иметь "нормальную" (отслеживающую) ветку. Но вам следует дважды подтвердить это.

Ответ 4

Может кто-нибудь объяснить, что я делаю неправильно, или предложить альтернативный метод?

Вы пробовали использовать DMAIC? D efine, M, A nalyze, I mprove, C ontrol.

D - мое репо по-прежнему остается большим после удаления файла из истории git.
M - Определите размер нового репо с помощью git init, чтобы установить базовый уровень.
A - Идентифицировать, проверять и выбирать основную причину. Эксперимент с git-repo-analysis.
I - Идентифицировать, тестировать и внедрять решение. Возможно, BFG Repo-Cleaner поможет. Может быть, это не так. C - Поддерживайте прибыль. Посмотрите на что-то вроде Git LFS или другой соответствующий метод управления.

Я также хочу иметь возможность исправить удаленное репо на Github.

Это будет зависеть от того, как вы решите проблему. Для exaple, при использовании BFG для обрезки файлов из истории, он будет переписывать историю и обновлять SHA, поэтому здесь будут некоторые давать и принимать в зависимости от ваших конкретных потребностей и желаемых результатов.