Не могу нажать на GitHub из-за большого файла, который я уже удалил

272

В настоящее время у меня есть

  1. Пустой репозиторий GitHub
  2. Репозиторий SSH-сервера (основной)
  3. Местный репо

Репозиторий SSH-сервера был самым современным репо (производственным сайтом), поэтому я сделал клон Git оттуда к локальному. Затем я попытался сделать git pushGitHub.

Все прошло хорошо, но потом что-то говорило о filename.gz, слишком большом для GitHub. Мне не нужен был этот файл, поэтому я запустил несколько команд Git, чтобы избавиться от него из кеша Git, а затем отправил обратно на SSH-сервер.

Я не вижу большой файл локально, но он все еще находится на SSH-сервере, хотя git diffничего не возвращает и git push возвращает «Все обновлено» - и даже если файл не отображается в локальном репо, когда я пытаюсь нажать на GitHub Я все еще получаю ошибку об этом

remote: ошибка: файл fpss.tar.gz равен 135,17 МБ; это превышает ограничение размера файла GitHub в 100 МБ

Я следовал инструкциям в разделе «Исправление проблемы», перечисленным в справке GitHub, так что, разве этого было недостаточно?

Как файл остается в эфире, если он не локальный или не указан в git status / diff / push?

Кевин В.
источник
2
Файл все еще там в истории. Вам нужно уничтожить историю, возможно, раздавив коммиты, которые добавили и удалили файл.
Шахбаз
@Shahbaz Я следовал инструкциям в разделе «Исправление проблемы», перечисленным на этом сайте ... разве этого было недостаточно? help.github.com/articles/working-with-large-files
Кевин В.
Команда там более продвинутая, чем мои познания в git, поэтому я не могу сказать точно. Во всяком случае, если git log -- the_big_fileвам что-то возвращает, то файл все еще в истории.
Шахбаз
@Shahbaz, который ничего не возвращает> <
Кевин В.
Может быть, вы также толкаете другие ветви, где файл существует? Кроме того, если файл все еще находится на сервере, почему бы git pushсказать, что все обновлено? Поскольку вы изменили историю, она должна была жаловаться на то, что толчок невозможен и вам придется его форсировать.
Шахбаз

Ответы:

448

Ты можешь использовать

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

Это удалит все в истории этого файла. Проблема в том, что файл присутствует в истории.

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

МакГайвер
источник
24
Сработало для меня, но мне пришлось «заставить» это: git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file / dir>' -f HEAD
alexoviedo999
31
Эта команда изменяет хэши ваших коммитов, что может быть реальной проблемой, особенно в общих репозиториях. Это не должно выполняться без понимания последствий.
Крис
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
Жоао Абрантиш
69

Я нашел сквош более полезным, чем filter-branch. Я сделал следующее:

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

Особый случай (от пользователя @lituo): Если вышеописанное не работает, то у вас может быть этот случай. Фиксация 1 включала в себя большой файл, а передача 1 не удалась из-за большой ошибки файла. Commit 2 удалил большой файл,git rm --cached [file_name]но Push 2 все еще не прошел. Вы можете выполнить те же действия, что и выше, но вместо использованияHEAD~3используйтеHEAD~2.

Но я не фанат класс
источник
2
Сработало для меня, просто пришлось заново объединить изменения из трех коммитов обратно в мой локальный репозиторий, прежде чем сработал пуш-сквош.
dasWesen
5
Это НАМНОГО лучше, чем главный ответ. Верхний ответ портит всю вашу историю коммитов.
manic.coder
Не
Хирак Саркар
3
Это, безусловно, единственный ответ, который исправляет большие незафиксированные или зафиксированные файлы, без полного уничтожения репозитория! Проголосовал, чтобы он мог перейти на вершину :-)
Ælex
1
@ но я не фанат класса: спасибо большое! это сработало как очарование :)
Пуджа Гупта
64

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

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

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

Shreya
источник
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"
BlueMoon93
источник
1
Это решение не будет работать, так как файл больше не находится в индексе git (это приводит к untrackedсписку файлов в git status.
loretoparisi
Ничего не происходит После применения это уменьшило общее количество файлов, но после показа процесса на 99% оно снова зависло. Любое предложение, что я скучаю?
Код
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 - postBuffer = 999999999

После этого толчок прошел!

Андре Одендаал
источник
1
Еще одна проблема, с которой мне пришлось столкнуться при удалении большого файла (как указано выше), заключалась в том, что в одной из папок содержался хэш-символ #. Это не вызвало никаких проблем для нормальной работы git, однако git rmмне нужно было дать полное имя пути к хранилищу для файла и экранировать # с обратной косой чертой, чтобы заставить его работать
jacanterbury
это сработало и для меня. Я избежал reset hardшага внизу страницы простым нажатием. czettner.com/2015/07/16/…
Монте Хейворд,
Это сработало после запуска 'git push -f origin'
kezzos
12

Почему GitHub отказывается от моего репо, даже после того, как я удалил большой файл?

Git хранит полную историю вашего проекта, поэтому, даже если вы «удалите» файл из своего проекта, в репозитории Git по-прежнему будет храниться копия файла в его истории, и если вы попытаетесь отправить его в другое хранилище (например, размещенное на 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
5

Я перепробовал все вышеперечисленные методы, но ни один из них не работает для меня.

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

  1. Прежде всего, вам нужен чистый, современный локальный репо. Удалить все чертовски большие файлы.

  2. Теперь создайте новую папку ВНЕ своей папки репо и используйте «Git create репозиторий здесь», чтобы сделать его новым Git-репозиторием, назовем его new_local_repo. Это оно! Все вышеперечисленные методы говорят, что вы должны очистить историю ... ну, я сыт этим по горло, давайте создадим новый репо, у которого вообще нет истории!

  3. Скопируйте файлы из вашего старого, испорченного локального репо в новое, красивое репо. Обратите внимание, что зеленый логотип на значке папки исчезнет, ​​это многообещающе, потому что это новый репо!

  4. Зафиксируйте локальную ветвь и затем нажмите на удаленную новую ветку Давайте назовем это new_remote_branch. Если вы не знаете, как получить доступ к новому локальному репо, отправьте его в Google.

  5. Congrats! Вы отправили свой чистый, обновленный код на GitHub. Если вам больше не нужна удаленная главная ветка, вы можете сделать ваш new_remote_branch новой веткой. Если вы не знаете, как это сделать, Google это.

  6. Последний шаг, пришло время удалить испорченный старый локальный репо. В будущем вы будете использовать только new_local_repo.

Шуайбин Чанг
источник
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для отмены.
Уильям Ху
источник
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 Выполняет git reset origin / master

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

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

Ньороге Матху
источник
0

Поэтому я столкнулся с определенной ситуацией: я клонировал репозиторий из gitlab, который содержал файл размером более 100 МБ, но был удален в какой-то момент в истории git. Позже, когда я добавил новое частное репозиторий github и попытался перейти к новому репо, я получил печально известную ошибку "file too large" К этому моменту у меня больше не было доступа к исходному репозиторию gitlab. Тем не менее, я все еще был в состоянии перейти к новому частному bfg-repo-cleanerрепозиторию github, используя локальный репозиторий на моей машине:

$ 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, Вы должны увидеть кучу перезаписей, показанных на вашей консоли, которая заканчивается:

    рм "имя файла" и

    последняя строка Ref была переписана.

Это сделано.

Дерево ДР
источник
-1

Я добавляю к первому ответу.

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch' HEAD

Будет возникать конфликт слияния от источника / мастера.

Ваша ветка и «origin / master» разошлись и имеют по 114 и 109 разных коммитов соответственно. (используйте "git pull", чтобы объединить удаленную ветку с вашей)

Пожалуйста, запустите это

git reset --hard origin / master

Он отбросит все мои поэтапные и неустановленные изменения, забудет все в моей текущей локальной ветке и сделает его точно таким же, как origin / master.

РАХУЛ КУМАР
источник