Удалить файл из репозитория 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 / packed-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 - чтобы, наконец, удалить эти объекты

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