Git: Як видалити файл з історичної фіксації?


113

У мене є фіксація з id 56f06019 (наприклад). У цій комісії я випадково запустив великий файл (50Mb). В інший фільтр я додаю той самий файл, але в потрібному розмірі (невеликий). Тепер моє репо, коли я клонуюсь, занадто важке :( Як видалити цей великий файл з історії репо, щоб зменшити розмір мого репо?


у моєму випадку це не великий файл, а файл конфігурації, що містить кредити бази даних. Я вивчав git, на той час я не знав про .gitignore.
Раші


Відповіді:


165

У розділі 9 книги Pro Git є розділ " Видалення об'єктів" .

Дозвольте коротко окреслити кроки тут:

git filter-branch --index-filter \
    'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \
    --tag-name-filter cat -- --all

Як і варіант, описаний раніше, filter-branchце операція перезапису. Якщо ви опублікували історію, вам доведеться --forceпідштовхнути нові оновлення.

filter-branchПідхід є значно потужнішим , ніж rebaseпідхід, так як воно

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

filter-branch також зберігає резервні копії, тому розмір репо не зменшиться негайно, якщо у вас не закінчиться час відмови та збирання сміття:

rm -Rf .git/refs/original       # careful
git gc --aggressive --prune=now # danger

1
Варто зазначити, що це, здається, не працює під Windows cmd.exe. Однак, здається, працює добре під цигуніном.
Підроблена назва

2
Наведений вище фільтр філії git працював, використовуючи подвійні лапки замість одинарних лапок (на Windows Server 2012 cmd.exe)
JCii

1
Для мене працював цей командний рядок фільтр-гілка. git filter-branch --force --index-filter 'git rm --ignore-unmatch --cached PathTo/MyFile/ToRemove.dll' -- fbf28b005^.. Тоді, rm --recursive --force .git/refs/originalа rm --recursive --force .git/logs потім я використав git prune --expire now і git gc --aggressive це працювало для мене краще, ніж ваші точні кроки, перелічені вище. Дякуємо, що включили посилання на книгу Git Pro, оскільки вона була неоціненною.
dacke.geo

Після команди фільтра-гілки, єдиний спосіб , яким я міг би отримати розмір .git вниз папки повинен був слідувати команда тут: stackoverflow.com/questions/1904860 / ... мерзотник -c gc.reflogExpire = 0 -c дс. reflogExpireUnreachable = 0 -c gc.rererelated = 0 \ -c gc.rerereun разрешительно = 0 -c gc.pruneExpire = тепер gc "$ @"
Стів Ардіс

Для скорочення репо я використав команди, перелічені в git filter-branch doc: git-scm.com/docs/…
Людовик Ронсін


0

Вам потрібно буде git rebase в інтерактивному режимі див. Приклад тут: Як я можу видалити комісію на GitHub? і як видалити старі коміти .

Якщо ваша комісія становить HEAD мінус 10 комісій:

$ git rebase -i HEAD~10

Після видання вашої історії вам потрібно натиснути "нову" історію, вам потрібно додати +силу (див. Рефлекс у параметрах натискання ):

$ git push origin +master

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


3
Це не вилучає великий файл з історії. Також канонічним способом змусити натиснути є git push --forceабо git push -f(що не вимагає, щоб люди знали ціль відгалуження)
12.12

Виходячи з питання, новий файл точно такий же, як і старий файл, тобто той самий шлях. Ось чому ви не можете безпосередньо використовувати git rmна шляху.
Loïc d'Anterroches

2
@sehe, якщо ви виконаєте ребазування, усуваючи фіксацію з величезним файлом, це втрачено назавжди
vonbrand

@vonbrand лише з тієї гілки, яку ви перезавантажили. Я не припускаю, що гілка "від" видаляється. Але так, якщо ви видалите гілку дерева версії, це допоможе: _
вересня 1313

@sehe, звичайно, ви повинні переслідувати всі гілки, які містять правопорушення. Якщо це буде перед тим, як заробити репо, вам доведеться зробити багато реорганізації. Але інструмент для цього є база даних.
vonbrand

0

Я спробував використати наступну відповідь на Windows https://stackoverflow.com/a/8741530/8461756

Одинарна цитата не працює на Windows, потрібні подвійні лапки.

Слідом працював для мене.

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PathRelativeRepositoryRoot / bigfile.csv" - --all

Після видалення великого файлу я зміг надіслати свої зміни до github master.


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