Как удалить неиспользуемые объекты из репозитория git?

Я случайно добавил, зафиксировал и отправил огромный двоичный файл с моим самым последним коммитом в Git-репозиторий.

Как я могу заставить Git удалить объект (ы), которые были созданы для этого коммита, так что мой .git каталог снова сжимается до нормального размера?

Изменить: Спасибо за ваши ответы; Я попробовал несколько решений. Никто не работал. Например, тот из GitHub удалил файлы из истории, но .git размер каталога не уменьшился:

$ BADFILES=$(find test_data -type f -exec echo -n "'{}' " \;)

$ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $BADFILES" HEAD
Rewrite 14ed3f41474f0a2f624a440e5a106c2768edb67b (66/66)
rm 'test_data/images/001.jpg'
[...snip...]
rm 'test_data/images/281.jpg'
Ref 'refs/heads/master' was rewritten

$ git log -p # looks nice

$ rm -rf .git/refs/original/
$ git reflog expire --all
$ git gc --aggressive --prune
Counting objects: 625, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (598/598), done.
Writing objects: 100% (625/625), done.
Total 625 (delta 351), reused 0 (delta 0)

$ du -hs .git
174M    .git
$ # still 175 MB :-(

8 ответов

Я ответил на это в другом месте, и буду копировать здесь, так как я горжусь этим!

... и без дальнейших церемоний, могу я представить вам этот полезный скрипт, git-gc-all, гарантированно удаляющий весь ваш мусор git до тех пор, пока они не могут появиться с дополнительными переменными конфигурации:

git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 \
  -c gc.rerereresolved=0 -c gc.rerereunresolved=0 \
  -c gc.pruneExpire=now gc "$@"

Опция --aggressive может быть полезна.

ПРИМЕЧАНИЕ: это удалит ВСЕ непривязанные вещи, так что не приходите ко мне плакать, если позже решите, что хотите оставить некоторые из них!

Вам также может понадобиться запустить что-то вроде этого, о, дорогой, мерзавец сложен!!

git remote rm origin
rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/
git for-each-ref --format="%(refname)" refs/original/ |
  xargs -n1 --no-run-if-empty git update-ref -d

Я положил все это в сценарий, здесь:

http://sam.nipl.net/b/git-gc-all-ferocious

Ваш git reflog expire --all это неверно. Он удаляет записи reflog старше срока истечения, который по умолчанию равен 90 дням. использование git reflog expire --all --expire=now,

Мой ответ на аналогичный вопрос посвящен проблеме реального удаления неиспользуемых объектов из хранилища.

1) Удалите файл из репозитория git (а не из файловой системы):

  • git rm --cached path/to/file

2) Сократите репо, используя:

  • git gc,

  • или же git gc --aggressive

  • или же git prune

или сочетание вышеперечисленного, как предлагается в этом вопросе: Уменьшите размер хранилища git

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

Если вы хотите, чтобы бинарный файл был доступен в репо для других людей, то нет реального способа сделать то, что вы хотите. Это почти все или ничего.

Ключ для меня оказался запущенным git repack -A -d -f а потом git gc чтобы уменьшить размер одного git пакета, который у меня был.

Hy!

Git получает только те объекты, которые ему действительно нужны, при клонировании репозиториев (если я правильно понимаю)

Таким образом, вы можете изменить последний коммит, удалив файл, добавленный по ошибке, а затем перенести изменения в удаленный репозиторий (с опцией -f также перезаписать старый коммит на сервере)

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

При желании, если вы также хотите удалить ненужные файлы с сервера, вы можете удалить репозиторий на сервере и отправить свою только что клонированную копию (с полной историей)

git filter-branch --index-filter 'git rm --cached --ignore-unmatch Filename' --prune-empty -- --all

Не забудьте изменить Filename за тот, который вы хотите удалить из хранилища.

Смотрите раздел "Удаление объектов" в книге Pro Git:

http://git-scm.com/book/en/Git-Internals-Maintenance-and-Data-Recovery

Обновление: см. Также очиститель репозитория BFG: http://rtyley.github.io/bfg-repo-cleaner/

В 2020 году документация для git-filter-branch не одобряет его использование и рекомендует использовать альтернативу, такую ​​как git-filter-repo. Его также можно использовать вместо BFG.

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

Другие вопросы по тегам