Удалить файл из репозитория 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, и я действительно не хочу, чтобы они там были ... И я не хочу сбрасывать репозиторий на 0 :(

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

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

person Boris Churzin    schedule 29.01.2010    source источник
comment
Возможные дубликаты: stackoverflow.com/questions/2100907/ stackoverflow.com/questions/872565/   -  person Greg Bacon    schedule 29.01.2010
comment
zneak - мой вопрос в заголовке. gbacon - те пробовал, файлы остались в паке ...   -  person Boris Churzin    schedule 30.01.2010
comment
Если вы посмотрите на статью, на которую есть ссылки в дубликатах, она покажет, как сжать хранилище объектов после удаления проблемного файла.   -  person Kyle Butt    schedule 30.01.2010
comment
То есть git gc --aggressive --prune Не получилось, перепаковал все, а файл все еще там ...   -  person Boris Churzin    schedule 30.01.2010
comment
Отображается ли рассматриваемый BLOB-объект в выходных данных git fsck --full --unreachable?   -  person Dan Moulding    schedule 01.02.2010
comment
нет, git fsck --full вообще ничего не возвращает   -  person Boris Churzin    schedule 01.02.2010
comment
Это была палочка-выручалочка. Мысленное примечание: всегда добавляйте потенциально огромные файлы * .log в .gitignore. После этого перешел с репо с 800 МБ до 6 МБ.   -  person JackCA    schedule 19.08.2010
comment
шаг 2 и 3 в одном for i in `git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5` ; do git rev-list --objects --all | grep $(echo $i | sed 's/ .*//g') ; done   -  person geermc4    schedule 08.01.2013


Ответы (8)


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

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

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

rm -rf .git/refs/original

2) Удалить все записи рефлога:

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

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

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

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

git fsck --full --unreachable

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

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

git repack -A -d

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

5) Удалите незакрепленные (недоступные) объекты

git prune

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

person Dan Moulding    schedule 01.02.2010
comment
Ура !!! Я тебя люблю ! Проблема была в файле pack-refs, там были refs / remotes / origin / master с тех пор, как я делал резервную копию на каком-то сервере ... как только я его удалил, все стало исчезать ... Спасибо! (обновление тела вопроса полным решением) - person Boris Churzin; 02.02.2010

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

Вам следует внимательно выполнить следующие действия: 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.

person Roberto Tyley    schedule 02.04.2013
comment
Очищает ли это частные данные из удаленных репозиториев после отправки? - person Thomas Lauria; 23.07.2013
comment
@ThomasLauria Ага, те же очищенные ссылки отправляются в удаленные репозитории при нажатии - инструкции на странице rtyley.github.io/bfg-repo-cleaner/#usage должен охватывать его. Если у вас есть контроль над удаленным репо, вы также можете запустить на нем git gc --prune = now --aggressive после нажатия, чтобы гарантировать, что мертвые объекты также будут немедленно удалены из него. - person Roberto Tyley; 23.07.2013
comment
@RobertoTyley Это может привести к появлению двух коммитов, которые появляются друг за другом в истории и имеют одно и то же дерево (если один из этих коммитов добавил только удаленный файл (ы)). Вы знаете простой способ удалить такие коммиты из истории коммитов, поскольку они кажутся искусственными? - person user44400; 19.04.2018
comment
@RobertoTyley Я думаю, это касается другого вопроса. В описанном мной случае задействовано только одно хранилище. Но git filter-branch --prune-empty, похоже, является решением моего вопроса (хотя с помощью другого инструмента, пожалуйста, дайте мне знать, может ли BFG Repo-Cleaner сделать то же самое). - person user44400; 19.04.2018

Я обнаружил, что это очень полезно в отношении удаления всей папки, поскольку приведенное выше мне не помогло: 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
person Mike Averto    schedule 20.03.2013

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

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

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

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

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

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

git gc --prune='0 days ago'
person Wayne Conrad    schedule 29.01.2010
comment
Ага, попробовал, файлы в пакете остались, и размер не сильно изменился ... - person Boris Churzin; 30.01.2010
comment
Я просто сделал git-песочницу и попробовал. Здесь тоже ничего хорошего. Посмотрим, что я смогу выяснить. - person Wayne Conrad; 30.01.2010
comment
Тот, что в ответе? :) Это то же самое, что я опубликовал, и он все еще оставляет файл в пакете ... попробуйте песочницу git, выполните git gc, чтобы он упаковал файл, а затем запустите это ... - person Boris Churzin; 30.01.2010
comment
О, незакрепленные предметы? См. Выше. Я был бы склонен просто позволить им убрать мусор за две недели (по умолчанию для gc); Убивать все незакрепленные объекты - все равно что выливать мусор - я теряю возможность вернуть все, что случайно удалил. - person Wayne Conrad; 30.01.2010
comment
:) попробовал и этот ... избавился от некоторых файлов, но самые большие остались там ... - person Boris Churzin; 31.01.2010
comment
Drats. Я думал, что это сработает. Существуют ли файлы в каких-либо других ветках? - person Wayne Conrad; 31.01.2010
comment
У меня нет других веток :) Но я думаю, что, возможно, я однажды переместил файл из одного каталога в другой ... Я запускаю ветвь filter на обоих путях, но это не помогает ... - person Boris Churzin; 31.01.2010

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

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

Но в вашем случае можно проверить один трюк: clone ваше «очищенное» репозиторий Git и посмотрите, имеет ли клон подходящего размера.

(«очищенное» репо - это репо, в котором вы применили filter-branch, а затем gc и prune)

person VonC    schedule 01.02.2010
comment
Да, уже протестировал, и сейчас снова протестировал, он уменьшил репозиторий на 2k :), а файлы все еще там ... - person Boris Churzin; 01.02.2010
comment
Странно git count-objects -v -> count: 0, size: 0, in-pack: 10021, packs: 1, size-pack: 244547, prune-packable: 0, garbage: 0 но: git clone test1 test2 -> Checking out files: 100% (8509/8509), done - person Boris Churzin; 01.02.2010

Это должно быть предусмотрено командой git obliterate в Git Extras (https://github.com/visionmedia/git-extras).

git obliterate <filename>
person Spain Train    schedule 25.03.2013

У меня была такая же проблема, и я нашел отличный учебник на 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
person Cyril Leroux    schedule 12.03.2013
comment
Ответы только по ссылкам крайне не приветствуются в Stack Overflow, потому что, если в будущем ссылка разорвется, ответ станет бесполезным. Пожалуйста, рассмотрите возможность обобщения соответствующей информации, содержащейся в ссылке в вашем ответе. - person ; 04.04.2014