Не вдається натиснути на GitHub через великий файл, який я вже видалив


272

В даний час я

  1. Порожній репо GitHub
  2. РЕПО сервера SSH (основний)
  3. Місцевий репо

РЕПО сервера SSH було найсучаснішим репо (виробничий сайт), тому я зробив клон Git звідти в локальний. Потім я спробував зробити git pushGitHub.

Все пішло нормально, але тоді це щось говорило про те, що filename.gz є занадто великим для GitHub. Мені цей файл не знадобився, тому я запустив кілька команд Git, щоб позбутися його з кешу Git, а потім відправив назад на SSH-сервер.

Я не бачу великого файлу локально, але він все ще знаходиться на сервері SSH, хоча git diffнічого не повертає і git push повертається "Все актуально" - І навіть якщо файл не відображається в локальній репо, коли я намагаюся натиснути на GitHub Я все ще отримую помилку з цього приводу

віддалений: помилка: Файл fpss.tar.gz становить 135,17 Мб; це перевищує обмеження розміру файлу GitHub в 100 Мб

Я дотримувався кроків у розділі "Виправлення проблеми", вказаному в довідці GitHub так чи не повинно було цього бути?

Як файл все ще знаходиться в ефірі, коли він не локальний або не вказаний у статусі git / diff / push?


2
Файл все ще є в історії. Вам потрібно знищити історію, можливо, розбивши коміти, які додали та видалили файл.
Шахбаз

@Shahbaz Я дотримувався кроків у розділі "виправлення проблеми", зазначених на цьому веб-сайті ... чи цього не повинно було бути достатньо? help.github.com/articles/working-with-large-files
Кевін В.

Команда там більш досконала, ніж моє знання git, тому я не можу сказати. У будь-якому випадку, якщо git log -- the_big_fileвам щось повертається, то файл все ще є в історії.
Шахбаз

@Shahbaz, який повертає nothings> <
Kevin W.

Можливо, ви також висуваєте інші гілки, де існує файл? Крім того, якщо файл все ще знаходиться на сервері, чому б це зробитиgit push сказати, що все актуально? Оскільки ви змінили історію, ви повинні були поскаржитися, що натискання неможливе і що вам доведеться змусити його.
Шахбаз

Відповіді:


446

Можна використовувати

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file/dir>' HEAD

Це видалить усе в історії цього файлу. Проблема полягає в тому, що файл присутній в історії.

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


23
Працювало для мене, але мені довелося це «змусити»: git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file / dir>' -f HEAD
alexoviedo999

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

6
Чи слід замінити <file / dir> на ім'я файлу чи dir, що спричиняє проблему?
Девід Роден

12
Зауважте, що якщо ви хочете застосувати ці зміни до ВСІХ гілок, вам потрібно використовувати --allпрапор замістьHEAD
Nick Spreitzer

9
Я отримую:Rewrite 657560fa18c030bcfac9132ce1c3541e84a5bc2c (1/10) (0 seconds passed, remaining 0 predicted) /usr/lib/git-core/git-filter-branch: 1: eval: Syntax error: end of file unexpected
Жоао Абрантес

68

Я вважав, що гарбуз корисніше, ніжfilter-branch . Я зробив наступне:

  1. Місцеве видалення великих файлів.
  2. Звернути місцевих делетів.
  3. Програмне відновлення назад X кількість комітів (для мене це було 3): git reset --soft HEAD~3 .
  4. Потім повторно повторіть усі зміни (сквер AKA) git commit -m "New message for the combined commit"
  5. Нажимайте нарізані фішки.

Особливий випадок (від користувача @lituo): Якщо вище не працює, то у вас може виникнути такий випадок. Комісія 1 включала великий файл, а натискання 1 зробити не вдалося через велику помилку файлу. Команда 2 вилучила великий файл,git rm --cached [file_name]але натискання комітету 2 все ще не вдалося. Ви можете виконувати ті ж самі кроки, що описані вище, але замість цьогоHEAD~3використовуйтеHEAD~2.


2
Працював для мене, просто довелося повторно об'єднати зміни з трьох комітетів назад у моє місцеве сховище до того, як поштовх сквош запрацював.
dasWesen

5
Це набагато краще, ніж найкраща відповідь. Верхня відповідь накручує всю вашу історію фіксацій.
manic.coder

Не виправили мою проблему
Хірак Саркар

3
Це, безумовно, єдина відповідь, яка виправляє великі незапущені або довірені файли, не занурюючи повністю сховище! Запропоновано, щоб він міг рухатися до вершини :-)
Ælex

1
@ але я не клас обгортки: велике спасибі! це спрацювало як шарм :)
POOJA GUPTA

62

Ось щось, що мені здалося, дуже корисно, якщо ви вже зібралися зі своїм репо, перш ніж звертатися за допомогою. Перший тип:

git status

Після цього ви повинні побачити щось уздовж рядків

On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

Важлива частина - "2 коміти"! Звідси продовжуйте і введіть:

git reset HEAD~<HOWEVER MANY COMMITS YOU WERE BEHIND>

Так, у наведеному вище прикладі можна набрати:

git reset HEAD~2

Після того, як ви набрали це, ваш "git status" повинен сказати:

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Звідти ви можете видалити великий файл (якщо припустити, що ви цього ще не зробили), і вам вдасться повторно зробити все, не втрачаючи роботу.
Я знаю, що це не дуже фантастична відповідь, але я сподіваюся, що це допоможе!


11
Переможець. Просте, чисте, ефективне рішення, створене з git. Любов відповідає так.
Даніельс

3
це найкраще рішення.
школярка

40

Якщо файл був доданий із вашою останньою комісією , і ви не натиснули у віддалений сховище , ви можете видалити файл та внести зміни до комісії, взятої звідси :

git rm --cached giant_file
    # Stage "giant_file" for removal with "git rm"
    # Leave it on disk with "--cached". if you want to remove it from disk
    # then ignore the "--cached" parameter
git commit --amend -CHEAD
    # Commit the current tree without the giant file using "git commit"
    # Amend the previous commit with your change "--amend" 
    # (simply making a new commit won't work, as you need
    # to remove the file from the unpushed history as well)
    # Use the log/authorship/timestamp of the last commit (the one we are
    # amending) with "-CHEAD", equivalent to --reuse-message=HEAD
git push
    # Push our rewritten, smaller commit with "git push"

1
Це рішення не працюватиме, оскільки файл більше не входить до індексу git (це призводить до untrackedсписку файлів за адресою git status.
loretoparisi

Нічого не відбувається. Після застосування це зменшило загальну кількість файлів, але після показу процесу 99% він знову застряг. Якась пропозиція, чого мені не вистачає?
CoDe

4
що означає -CHEAD?
Ерін

1
Що робити, якщо я хочу спробувати це з певного комітету - не з останнього зобов’язання? Я спробував, git rm --cached giant_file commit_idале не вийшло :(
puifais

@puifais Я б повернувся до попередньої фіксації, виконую ці дії, а потім об'єднаюся з поточною. Я не впевнений, чи це найкращий підхід, я не фахівець з Git
BlueMoon93

13

У мене була подібна проблема, і я скористався кроком вище, щоб видалити файл. Це спрацювало чудово.

Потім я отримав помилку у другому файлі, який мені потрібно було видалити: remote: error: File <path/filename> is 109.99 MB; this exceeds GitHub's file size limit of 100.00 MB

Я спробував той же крок, отримав помилку: "A previous backup already exists in <path/filename>"

З досліджень на цьому веб-сайті я використав команду:git filter-branch --force --index-filter "git rm --cached --ignore-unmatch <path/filename>" --prune-empty --tag-name-filter cat -- --all

Працювало чудово, і великі файли було видалено.

Неймовірно, що натискання все ж не вдалося з черговою помилкою: error: RPC failed; curl 56 OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104 fatal: The remote end hung up unexpectedly

Це я виправив, змінивши безпосередньо файл .git config - postBuffer = 999999999

Після цього поштовх пройшов!


1
Додатковий готч, який мені довелося зіткнутися з видаленням великого файлу (як вище), полягав у тому, що одна з папок мала в ньому хеш-символ. Це не спричинило жодних проблем для нормальної роботи git, однак для git rmмене потрібно було вказати повну назву шляху до файлу сховища та уникнути # із зворотним косою рисою, щоб змусити його працювати
jacanterbury

це теж працювало для мене. Я уникав reset hardкроку внизу сторінки простим натисканням. czettner.com/2015/07/16/…
Монте Хейвард

Це спрацювало після запуску "git push -f origin"
кецо

12

Чому GitHub відхиляє моє репо, навіть після того, як я видалив великий файл?

Git зберігає всю історію вашого проекту, тому навіть якщо ви 'видаляєте' файл із свого проекту, Git repo все ще має копію файлу в своїй історії, і якщо ви намагаєтеся перейти до іншого сховища (наприклад, одного, розміщеного в GitHub), то Git вимагає щоб віддалене репо має ту саму історію, що і місцеве репо (тобто ті самі великі файли в його історії).

Як я можу змусити GitHub прийняти репо?

Потрібно очистити історію Git свого проекту на локальному рівні, видаливши непотрібні великі файли з усієї історії, а потім використовувати лише «очищену» історію, що рухається вперед. Ідентифікатори комітетів Git, які стосуються комітетів, зміниться.

Як очистити великі файли з мого репортажу Git?

Найкращим інструментом для очищення небажаних великих файлів з історії Git є BFG Repo-Cleaner - це простіша та швидша альтернатива, git-filter-branchспеціально розроблена для видалення непотрібних файлів з історії Git.

Уважно дотримуйтесь інструкцій із використання , основна частина - саме це:

$ java -jar bfg.jar --strip-blobs-bigger-than 100M my-repo.git

Будь-які файли розміром понад 100 Мб (які не є вашими останніми комісіями) будуть видалені з історії вашого сховища Git. Потім можна використовувати git gcдля очищення мертвих даних:

$ git gc --prune=now --aggressive

BFG, як правило, принаймні на 10-50 разів швидше, ніж бігgit-filter-branch , і, як правило, набагато простіше у використанні.

Повне розкриття: Я автор BFG Repo-Cleaner.


1
У моєму випадку виникли додаткові ускладнення, які перешкоджали вишкрібанню. Інструмент BFG працював чудово. Дякую.
дантопа

Це феноменальне рішення
SexualPotatoes

4

У мене така ж проблема, і жодна з відповідей не працює на мене. Я вирішив наступними кроками:

1. Знайдіть, які коміти містять великий файл

git log --all -- 'large_file`

Найнижча комірка - найдавніша комісія у списку результатів.

2. Знайдіть той, що знаходиться безпосередньо перед найдавнішим.

git log

Припустимо, у вас:

commit 3f7dd04a6e6dbdf1fff92df1f6344a06119d5d32

3. Git rebase

git rebase -i 3f7dd04a6e6dbdf1fff92df1f6344a06119d5d32

Поради :

  1. Елемент списку
  2. Я просто вибираю, dropщоб коміти містять великий файл.
  3. Ви можете зіткнутися з конфліктами під час виправлення ребайдів і використовувати їх git rebase --continueдля продовження, поки не закінчите.
  4. Якщо щось пішло не так під час використання ребайду, git rebase --abortскасуйте його.

4

Я спробував усі вищеперелічені методи, але жоден з них не працює на мене.

Тоді я придумав власне рішення.

  1. Перш за все, вам потрібно чисте, сучасне місцеве репо. Видаліть усі чортові великі файли.

  2. Тепер створіть нову папку ЗОВНІШНІХ папок репо і скористайтеся "Git create repository here", щоб зробити це новим сховищем Git, назвемо його new_local_repo. Це воно! Усі вищевикладені методи говорили, що ви повинні очистити історію ... ну, мені це нудно, давайте створимо нове репо, яке взагалі не має історії!

  3. Скопіюйте файли зі свого старого, траханого місцевого репо в нове, прекрасне репо. Зауважте, що зелений логотип на піктограмі папки зникне, це перспективно, адже це нове репо!

  4. Приєднайтеся до місцевої гілки, а потім натисніть на віддалену нову гілку. Назвемо це new_remote_branch. Якщо ви не знаєте, як відштовхнутися від нового локального репо, відправте Google.

  5. Вітаю! Ви пересунули чистий і сучасний код на GitHub. Якщо віддалена головна гілка вам більше не потрібна, ви можете зробити свою new_remote_branch як нову головну гілку. Якщо ви не знаєте, як це зробити, Google.

  6. Останній крок, настав час видалити зіпсований старий локальний репо. Надалі ви використовуєте лише new_local_repo.



1

Рішення зберегти великі файли / папки в робочій папці

Це рядок, який працював над вирішенням заданої тут проблеми (з відповіді 1):

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file/dir>' HEAD

Ця команда також видаляє файл / dir, якщо файл / dir знаходиться в межах робочого дерева.

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

  1. Після цього запустіть помилку git reset HEAD^
  2. Додайте відповідний файл / папку у файл `.gitignore``.

  3. Продовжуйте, як завжди, git add .які можуть захоплювати інші файли / папки, але повинні захоплювати .gitignoreфайл. Далі - git commit -m"message"і нарештіgit push origin <branch_name>


0

це працювало для мене. документація від github Squashing Git Commits git reset origin / master

git checkout master && git pull;
git merge feature_branch;
git add . --all;
git commit -m "your commit message"

знайти тут документацію


0

Я додаю до першої відповіді.

git filter-branch - index-filter 'git rm -r - кешоване --ignore-unmatch' HEAD

Буде якийсь конфлікт злиття від походження / господаря.

Ваша філія та "походження / майстер" розійшлися і мають 114 та 109 різних доручень відповідно. (використовуйте "git pull", щоб об'єднати віддалену гілку у свою)

Будь ласка, запустіть це

git reset - жорстке походження / майстер

Це викине всі мої поетапні та нестандартні зміни, забуде все на моїй нинішній місцевій гілці та зробить це точно таким же, як походження / головний.


0

Тому я зіткнувся з особливою ситуацією: я клонував сховище з gitlab, яке містило файл, більший за 100 mb, але його було видалено в якийсь момент історії git. Потім пізніше, коли я додав нове приватне репо в github і намагався перейти на нове репо, я отримав сумнозвісну помилку "файл занадто великий". До цього моменту я більше не мав доступу до оригінального репортажу gitlab. Однак мені все ж вдалося перейти на нове приватне рефінансування github за bfg-repo-cleanerдопомогою локального сховища на моїй машині:

$ cd ~
$ curl https://repo1.maven.org/maven2/com/madgag/bfg/1.13.0/bfg-1.13.0.jar > bfg.jar
$ cd my-project
$ git gc
$ cd ../
$ java -jar bfg.jar --strip-blobs-bigger-than 100M my-project
$ cd my-project
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
$ git remote -v # confirm origin is the remote you want to push to
$ git push origin master

0

Іноді файл зберігається в історії відстеження, спробуйте виконати наступні дії:

  1. git commit, Якщо ви бачите режим створення із переліченим великим файлом, виконайте такі дії:
  2. git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch filename' HEAD. У вашій консолі ви побачите купу переписувань, яка закінчується на:

    rm 'ім'я файлу' та

    останній рядок Ref був переписаний.

Зроблено.

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