Удалить файл из репозитория 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
Ответ 8
Это должно быть включено командой git obliterate
в Git Extras (https://github.com/visionmedia/git-extras).
git obliterate <filename>