Удалить файл из репозитория Git (история)
(решено, см. Нижнюю часть тела вопроса)
Глядя на это уже давно, то, что у меня есть до сих пор:
- http://dound.com/2009/04/git-forever-remove-files-or-folders-from-history/ и
- http://progit.org/book/ch9-7.html
почти тот же метод, но оба они оставляют объекты в файлах пакета... Застрявший.
Что я пробовал:
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, и я действительно не хочу их там... И я не хочу сбрасывать репозиторий до 0: (
решение: Это самый короткий способ избавиться от файлы:
- проверка .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 резервное копирование -
git reflog expire --all --expire='0 days'
- удалить все свободные объекты -
git fsck --full --unreachable
- чтобы проверить, есть ли какие-либо свободные объекты -
git repack -A -d
- переупаковка -
git prune
- чтобы, наконец, удалить эти объекты
8 ответов
я не могу сказать наверняка без доступа к вашим данным репозитория, но я считаю, что, вероятно, один или несколько упакованных ссылок все еще ссылаются на старые коммиты до запуска git filter-branch
. Это объясняет, почему git fsck --full --unreachable
не вызывает большой двоичный объект недоступный объект, даже если у вас истек срок действия вашего 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
). Если вы найдете старые, которые не должны быть там, удалите их (удалите строку для этой ссылки).
после завершения очистки , если git fsck
уведомления "недоступные" объекты:
git fsck --full --unreachable
если это работает, и git fsck
теперь сообщает Ваш большой blob как недостижимый, вы можете перейти к следующему шагу.
4) переупакуйте упакованный архив(ы)
git repack -A -d
это гарантирует, что недостижимые объекты распаковываются и остаться распаковывается.
5) обрезать свободные (недостижимые) объекты
git prune
и это должно сделать это. Git действительно должен иметь лучший способ управлять упакованными refs. Может быть, есть лучший способ, о котором я не знаю. В отсутствие лучшего способа, ручное редактирование packed-refs
файл может быть единственный выход.
Я бы рекомендовал использовать BFG Repo-Cleaner, более простая и быстрая альтернатива git-filter-branch
специально разработан для перезаписи файлов из истории Git. Один из способов, которым он делает вашу жизнь проще здесь, заключается в том, что он фактически обрабатывает все ссылки по умолчанию (все теги, ветви, такие как refs/remotes/origin/master и т. д.), Но это также 10-50x быстрее.
вы должны тщательно следовать этим шагам здесь: http://rtyley.github.com/bfg-repo-cleaner/#usage - но основной бит таков: загрузите банка БДВ (требуется Java 6 или выше) и выполните следующую команду:
$ java -jar bfg.jar --delete-files file_name my-repo.git
любой файл с именем file_name
(это не в ваш последний commit) будет будет полностью удалены из истории вашего хранилища. Затем вы можете использовать git gc
чтобы очистить мертвые данные:
$ git gc --prune=now --aggressive
BFG, как правило, намного проще в использовании чем git-filter-branch
- параметры адаптированы вокруг этих двух общих вариантов использования:
- удаление Сумасшедшие Большие Файлы
- удаление Пароли, Учетные Данные и другие личные данные
полное раскрытие информации: я автор РЕПО-очистителя BFG.
Я нашел, что это очень полезно в отношении удаления целой папки, поскольку выше действительно не помогло мне: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
Я пытался избавиться от большого файла в истории, и ответы выше работал, до определенного момента. Смысл в том, что они не работают, если у вас есть теги. Если фиксация, содержащая большой файл, доступна из тега, то вам нужно будет настроить команду filter-branches таким образом:
git filter-branch --tag-name-filter cat \
--index-filter 'git rm --cached --ignore-unmatch huge_file_name' -- \
--all --tags
посмотреть: Как удалить конфиденциальные файлы из истории git
вышеперечисленное завершится ошибкой, если файл не существует в REV. в этом случае переключатель "--ignore-unmatch " исправит его:
git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch <filename>' HEAD
затем, чтобы получить все незакрепленные предметы из repostiry:
git gc --prune='0 days ago'
у вас есть различные причины для все еще большого размера РЕПО git после git gc
, Так как это не удаляет все свободные объекты.
я подробно эти причины в "уменьшить размер репозитория git"
но один трюк, чтобы проверить в вашем случае будет клон ваш "очищенный" git repo и посмотреть, имеет ли клон соответствующий размер.
("очищенное" РЕПО " - это то, где вы применили filter-branch
, а потом ... --2--> и prune
)
Это должно быть покрыто git obliterate
команда в Git Extras (https://github.com/visionmedia/git-extras).
git obliterate <filename>
у меня была такая же проблема и я нашел отличный учебник на GitHub, которые объясняют шаг за шагом как избавиться от файлов, которые вы совершено случайно.
вот небольшое резюме процедуры, как кекс предложил.
Если у вас есть файл с именем 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