Страницы

Поиск по вопросам

суббота, 21 декабря 2019 г.

очистить гит репозиторий от удалённых файлов

#git


Исторически возник большой репозиторий с несколькими десятками слабо связанных проектов. 
Начитался что разделить можно просто склонировав репозиторий и удалив ненужные проекты.
Склонировал, удалил. В проекте осталась только нужная папка, всё удалённое закомиттил,
но папка .git разрослась больше полугигабайта. При том что сам проект мегабайт 50.

Можно ли как-то почистить репозиторий от удалённых файлов и их истории? 
    


Ответы

Ответ 1



Для большого количества файлов или небольшого репозитория можно попробовать git filter-branch (см ответ от Arhad). Для большого количества файлов, массовых чисток, или удаления случайно вкоммитанных паролей стоит использовать утилиту BFG Repo-Cleaner. Она позволяет массово переписывать историю, и делает это очень быстро. На порядок быстрее git filter-branch. git filter-branch приходится вызывать для каждого файла, и он заново пересчитывает историю для каждого файла. Если файлов больше двух, это занимает вечность. Repo-Cleaner делает все за один проход. Из базовых примеров: Удаления файлов по маске: bfg --delete-files id_{dsa,rsa} my-repo.git Удаление папки целиком bfg --delete-folders somefolder --delete-files somefolder Удаление больших файлов bfg --strip-blobs-bigger-than 50M my-repo.git BFG по умолчанию не удаляет блобы в текущей ветке (HEAD), так что она идеально подходит для массовых чисток и переписывания истории без риска запороть последний коммит. В качестве гайда можно воспользоваться справкой GitHub по чистке репозиториев: Removing files from a repository's history Removing sensitive data from a repository

Ответ 2



Для того, чтобы удалить все упоминания конкретного файла из истории репозитория необходимо воспользоваться командой git filter-branch: git filter-branch --index-filter 'git rm --ignore-unmatch <путь>' где <путь> — это путь до удаляемого файла относительно текущей папки (не корня репозитория!). Учтите, что эта команда занимается переписыванием истории. То есть она берёт старое дерево и переносит его в новую копию, коммит за коммитом, после чего переназначает текущую указатель-ветку. Поэтому она работает очень медленно (около секунды на перенос одного коммита). Затем надо удалить пустые коммиты, образовавшиеся на месте тех, в которых были изменения только удалённых файлов: git filter-branch --commit-filter 'git_commit_non_empty_tree "$@"' HEAD После переписывания истории надо убрать все оставшиеся хвосты, чтобы как можно скорее уменьшить размер репозитория: Рвём все связи старых (исходных) коммитов с git reflog, чтобы сделать их недостижимыми: git reflog expire --all --expire-unreachable=0 Удаляем все недостижимые объекты (и упаковываем оставшиеся): git gc --prune=all --force Так как переписывание истории порождает новое дерево, которое не может быть наложено поверх одноимённой ветви любой другой копии репозитория, то ближайший git push придётся однократно сделать с ключом --force. То же самое касается и всех тех, кто будет выполнять git pull.

Ответ 3



Если у вас был репозиторий гит на полгигабайта и вы сделали коммит, в котором грохнули 99% этого репозитория - то давайте определимся, вам то, что было ранее уже не пригодится никогда и можно этот архив грохнуть, либо вам вам это нужно? Если нужно - то создайте новый репозиторий из оставшихся файлов, а в старый будете посматривать, если понадобится что-то глянуть. Если не нужно - схлопывайте историю коммитов оставив только последний (git rebase -i HEAD~100), а потом делайте git gc и git push --force

Комментариев нет:

Отправить комментарий