Удалить каталог навсегда из git
В моем личном репозитории git у меня есть каталог, содержащий тысячи небольших изображений, которые больше не нужны. Есть ли способ удалить их из всей истории git? Я пробовал
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch imgs" HEAD
и
git filter-branch --tree-filter 'rm -fr imgs' HEAD
но размер репо git остается неизменным. Любые идеи?
Спасибо
Ответы
Ответ 1
На самом деле ни один из этих методов не работал у меня.
Я считаю, что наиболее надежным было просто вытащить локально в другое репо:
git pull file://$(pwd)/myGitRepo
Это также избавляет вас от необходимости удалять старые теги.
см. рассказ в своем блоге:
http://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
Ответ 2
В книге ProGit есть интересный раздел Удаление объекта.
Это заканчивается следующим:
В вашей истории больше нет ссылки на этот файл.
Тем не менее, ваш reflog
и новый набор ссылок, добавленных Git, когда вы делали filter-branch
в разделе .git/refs/original
, так что вам нужно удалить их, а затем переупаковать базу данных. Вам нужно избавиться от всего, что имеет указатель на эти старые коммиты, прежде чем переупаковать:
$ rm -Rf .git/refs/original
$ rm -Rf .git/logs/
$ git gc
$ git prune --expire
(git prune --expire
не является обязательным, но может удалять содержимое каталога из свободных объектов)
Резервное копирование всего, прежде чем выполнять эти команды, на всякий случай;)
Ответ 3
git -filter-branch по умолчанию сохраняет старые ссылки ref в пространстве имен refs/original/*
.
Вам нужно удалить их, а затем сделать git gc --prune=now
Ответ 4
Брэндон Томсон спросил в комментарии к Rainer Blome, если это просто зафиксировало представление gitk или если refs действительно исчезнет. Хороший способ проверить это - запомнить один из хэшей sha1 (или уникальный префикс) старых коммитов и попробовать
$ git ls-tree hash-value
Это должно показать содержимое основной папки репозиториев, как это было в этой фиксации. После того, как
$ rm -Rf .git/refs/original
$ rm -Rf .git/logs/
как показано VonC, и удаляя строки refs/original/…
из .git/info/refs
и .git/packed-refs
, как показано Райнером Блом, окончательный
$ git gc --prune=now
сделано не только ref, но и старые объекты (коммиты, деревья и капли) уходят. Вышеприведенное доказательство git ls-tree hash-value
доказывает это.
Еще одна приятная команда, чтобы проверить это, - git count-objects -v
(запустите ее перед фильтром и после обрезки и сравните размер).
Примечание: Поскольку мне еще не разрешено комментировать другие ответы, мне пришлось написать новый, хотя он в основном сочетает предыдущие ответы.
Ответ 5
Если вы хотите пойти по пути ручной очистки, есть еще несколько файлов, которые могут также содержать
ссылку на исходную ветвь перед ветвью git -filter.
Например, я отфильтровал свою "домашнюю" ветку:
.git/info/refs:
179ad3e725816234a7182476825862e28752746d refs/original/refs/heads/home
.git/упакованный-refs:
179ad3e725816234a7182476825862e28752746d refs/original/refs/heads/home
После того, как я удалил эти строки, gitk больше не показывал старые коммиты.
Ответ 6
Поскольку это старый вопрос, возможно, в то время это было невозможно. Это также предполагает, что вы используете bash или cygwin.
Предупреждение: Вторая и третья строки будут навсегда удалять все коммиты, недоступные из ваших ветвей/тегов.
После запуска filter-branch
выполните
for ref in $(git for-each-ref --format='%(refname)' refs/original); do git update-ref -d $ref; done
git reflog expire --expire=now --all
git gc --prune=now
git for-each-ref --format='%(refname)'
получает имена ссылок, а git update-ref -d
удаляет ссылку. Как правило, лучше не изменять папку .git
напрямую, и, в частности, эта команда обрабатывает случай, когда ссылки ref находятся в packed-refs
.
Вторая и третья строки берутся непосредственно из Как очистить неиспользуемые боковые ветки в деревьях коммита?.