Як видалити невикористані об'єкти зі сховища git?


90

Я випадково додав, зафіксував і висунув величезний двійковий файл із самим останнім комітом до сховища 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 :-(

13
Тільки нагадування модераторам: це питання на 100% належить SO, а не суперкористувачеві.
VonC


Як уже згадувалося тут ( stackoverflow.com/questions/685319/… ), ви пробували перепакувати після вашого gc? git-repack -aа потім, git-prune-packedнаприклад. Дивіться blog.felipebalbi.com/2007/12/19/…
VonC

2
@Jonas: а що, якщо після всього цього ви клонуєте свій репо? Ви б тоді отримали клон із бажаним зменшеним розміром?
VonC

1
@Jonas: після того, як всі , що ви зробили ( filter-branch, gc, repack...), ні, ви не повинні бачити будь-яку погану фіксації на всіх. Це ознака того, що прибирання не відбулося належним чином.
VonC

Відповіді:


127

Я відповів на це в іншому місці і скопіюю тут, оскільки пишаюся цим!

... і без зайвих сумнівів, я можу представити вам цей корисний скрипт, 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 це складно !!

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


Як у stackoverflow.com/questions/1904860/… , ще раз вам +1.
VonC

18
відмінно: D Мій злий план отримати більше балів шляхом клонування відповідей спрацював !! 1;)
Сем Уоткінс

Так! Це спрацювало, але мені довелося запустити повний сценарій. Запустити лише команду gc (з параметрами конфігурації) було недостатньо.
Даніель

4
Від 102м до 160к .. ефективний та руйнівний
прусван

4
Велике спасибі за сценарій! Бонусна інформація: xargsКоманда видає помилку в OS X через невизнану опцію. Найпростіше рішення: встановіть GNU xargs за допомогою домашньої мови brew install findutilsта замініть xargsна gxargs.
qqilihq

26

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

Моя відповідь на подібне запитання стосується проблеми справді очищення невикористаних об’єктів зі сховища.


18

1) Видаліть файл з репозиторію git (і не з файлової системи):

  • git rm --cached path/to/file

2) Зменшити репо за допомогою:

  • git gc,

  • або git gc --aggressive

  • або git prune

або комбінація вищезазначеного, як пропонується у цьому питанні: Зменшити розмір сховища git


10

Цей посібник із видалення конфіденційних даних може застосовуватися тим же методом. Ви будете переписувати історію, щоб видалити цей файл із кожної редакції, в якій він був присутній. Це руйнує і спричинить конфлікти репо з будь-якими іншими виписками, тому попередьте попередньо всіх співавторів.

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


8

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


6

Привіт!

Git отримує лише необхідні йому об'єкти під час клонування сховищ (якщо я це правильно розумію)

Таким чином, ви можете внести зміни до останнього коміту, видаливши помилково доданий файл, а потім надіслати зміни до віддаленого сховища (з опцією -f, щоб також замінити старий коміт на сервері)

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

За бажанням, якщо ви також хочете видалити непотрібні файли з сервера, ви можете видалити сховище на сервері та надіслати свою нещодавно клоновану копію (яка має повну історію)



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

Не забудьте змінити Filenameтой, який ви хочете видалити зі сховища.


0

У 2020 році документація для git-filter-branch не рекомендує використовувати її та рекомендує використовувати таку альтернативу, як git-filter-repo . Його також можна використовувати замість BFG .

Зверніть увагу, що розділ про історію переписування в git book не оновлювався. Також немає рекомендацій GitHub щодо видалення конфіденційних даних.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.