Удалить файл из репозитория git (история)

(решено, см. нижнюю часть вопроса)

Глядя на это в течение долгого времени, то, что у меня есть до сих пор:

Практически тот же метод, но оба они оставляют объекты в файлах пакетов... Застрял.
Что я пробовал:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_name'
rm -Rf .git/refs/original
rm -Rf .git/logs/
git gc

Все еще есть файлы в пакете, и вот как я это знаю:

git verify-pack -v .git/objects/pack/pack-3f8c0...bb.idx | sort -k 3 -n | tail -3

И это:

git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch file_name" HEAD
rm -rf .git/refs/original/ && git reflog expire --all &&  git gc --aggressive --prune

То же самое...

Пробовал трюк git clone, он удалил некоторые из файлов (~ 3000 из них), но самые большие файлы все еще там...

У меня есть несколько старых файлов в репозитории, ~ 200M, и я действительно не хочу их там... И я не хочу, чтобы reset хранилище 0: (

РЕШЕНИЕ: Это самый короткий способ избавиться от файлов:

  • check.git/packed-refs - моя проблема заключалась в том, что у меня была строка refs/remotes/origin/master для удаленного репозитория, удалить ее, иначе git не удалит эти файлы
  • (необязательно) git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5 - для проверки самых больших файлов
  • (необязательно) git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98 - проверить, что это за файлы
  • git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_names' - удалить файл из всех версий
  • rm -rf .git/refs/original/ - удалить git backup
  • git reflog expire --all --expire='0 days' - для истечения всех свободных объектов
  • git fsck --full --unreachable - чтобы проверить, есть ли свободные объекты
  • git repack -A -d - переупаковка
  • git prune - для окончательного удаления этих объектов

Ответ 1

Я не могу сказать точно без доступа к данным вашего репозитория, но я считаю, что, вероятно, есть один или несколько упакованных ссылок, которые все еще ссылаются на старые коммиты, прежде чем вы запустите git filter-branch. Это объясняет, почему git fsck --full --unreachable не вызывает большой blob недостижимым объектом, даже если вы истекли ваш reflog и удалили исходные (распакованные) ссылки.

Вот что я сделал бы (после git filter-branch и git gc):

1) Убедитесь, что исходные ссылки отсутствуют:

rm -rf .git/refs/original

2) Истекает все записи reflog:

git reflog expire --all --expire='0 days'

3) Проверьте старые упакованные ссылки

Это может быть сложно, в зависимости от того, сколько у вас упакованных ссылок. Я не знаю каких-либо команд Git, которые автоматизируют это, поэтому я думаю, что вам придется делать это вручную. Сделайте резервную копию .git/packed-refs. Теперь отредактируйте .git/packed-refs. Проверьте старые ссылки (в частности, посмотрите, не упаковали ли какие-либо ссылки из .git/refs/original). Если вы найдете старые, которые не обязательно должны быть там, удалите их (удалите строку для этого ref).

После завершения очистки файла packed-refs см., если git fsck уведомляет недостижимые объекты:

git fsck --full --unreachable

Если это сработало, а git fsck теперь сообщает о вашем большом блобе как недоступном, вы можете перейти к следующему шагу.

4) Упакуйте упакованный архив (ы)

git repack -A -d

Это гарантирует, что недостижимые объекты будут распакованы и останутся распакованными.

5) Обрезать свободные (недоступные) объекты

git prune

И это должно сделать это. Git действительно должен иметь лучший способ управлять упакованными ссылками. Может быть, есть лучший способ, о котором я не знаю. В случае отсутствия лучшего способа ручное редактирование файла packed-refs может быть единственным способом.

Ответ 2

Я нашел, что это очень полезно в отношении удаления целой папки, поскольку приведенное выше не помогло мне: https://help.github.com/articles/remove-sensitive-data.

Я использовал:

git filter-branch -f --force \
--index-filter 'git rm -rf --cached --ignore-unmatch folder/sub-folder' \
--prune-empty --tag-name-filter cat -- --all

rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now

Ответ 3

Я бы рекомендовал использовать BFG Repo-Cleaner, более быструю и быструю альтернативу git-filter-branch, специально предназначенную для перезаписи файлов из Git история. Одним из способов облегчения вашей жизни является то, что он фактически обрабатывает все ссылки по умолчанию (все теги, ветки, такие как refs/remotes/origin/master и т.д.), Но также 10-50x быстрее.

Вы должны внимательно выполнить следующие шаги здесь: http://rtyley.github.com/bfg-repo-cleaner/#usage - но бит ядра - это просто: загрузите BFG jar (требуется Java 6 или выше) и выполните следующую команду:

$ java -jar bfg.jar  --delete-files file_name  my-repo.git

Любой файл с именем file_name (который не входит в ваш последний коммит) будет полностью удален из истории вашего репозитория. Затем вы можете использовать git gc для очистки мертвых данных:

$ git gc --prune=now --aggressive

BFG, как правило, гораздо проще в использовании, чем git-filter-branch - параметры настраиваются вокруг этих двух общих случаев использования:

  • Удаление Сумасшедших больших файлов
  • Удаление Паролей, учетных данных и других личных данных

Полное раскрытие: я являюсь автором BFG Repo-Cleaner.

Ответ 4

Я пытался избавиться от большого файла в истории, и вышеупомянутые ответы работали, вплоть до точки. Дело в том, что они не работают, если у вас есть теги. Если коммит, содержащий большой файл, доступен из тега, тогда вам нужно будет настроить команду filter-branches:

git filter-branch --tag-name-filter cat \
--index-filter 'git rm --cached --ignore-unmatch huge_file_name' -- \
--all --tags

Ответ 5

Смотрите: Как удалить конфиденциальные файлы из истории git

Вышеуказанное не будет выполнено, если файл не существует в rev. В этом случае переключатель "-ignore-unmatch" исправит его:

git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch <filename>' HEAD

Затем, чтобы получить все потерянные объекты из repostiry:

git gc --prune='0 days ago'

Ответ 6

У вас есть различные причины для большого размера git repo после git gc, поскольку не удаляет все незаполненные объекты.

Я подробно объясню эти причины в уменьшении размера хранилища git

Но один трюк для тестирования в вашем случае будет клонировать ваш "очищенный" git репо и посмотреть, есть ли клон соответствующий размер.

('' 'cleaned' repo 'является тем, где вы применили filter-branch, а затем gc и prune)

Ответ 7

У меня была такая же проблема, и я нашел отличный учебник на github, который объясняет шаг за шагом, как избавиться от файлов, которые вы случайно совершили.

Вот небольшое резюме процедуры, предложенной Cupcake.

Если у вас есть файл с именем file_to_remove для удаления из истории:

cd path_to_parent_dir

git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch file_to_remove' \
  --prune-empty --tag-name-filter cat -- --all