Удалить каталог навсегда из 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-репо остается неизменным. Есть идеи?
Спасибо
7 ответов
На самом деле ни один из этих методов не работал для меня. Я обнаружил, что самым надежным было просто потянуть локально в другое хранилище:
git pull file://$(pwd)/myGitRepo
Это также избавляет вас от необходимости удалять старые теги.
посмотреть историю в моем блоге: http://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
В книге 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
не является обязательным, но может удалить содержимое каталога из свободных объектов)
Сделайте резервную копию всего перед выполнением этих команд, на всякий случай;)
git-filter-branch по умолчанию сохраняет старые ссылки в refs/original/*
Пространство имен.
Вы должны удалить их, а затем сделать git gc --prune=now
Брендон Томсон спросил в комментарии к решению Rainer Blome, исправило ли это просто представление о gitk, или рефери действительно исчезнут. Хороший способ проверить это - вспомнить один из хэшей 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
сделал не только ссылки, но и старые объекты (коммиты, деревья и капли) уходят. Выше показано git ls-tree hash-value
доказывает это. Еще одна хорошая команда, чтобы проверить это git count-objects -v
(запустите его до фильтра-браха и после обрезки и сравните размер).
Примечание. Поскольку мне пока не разрешено комментировать другие ответы, мне пришлось написать новый, хотя в основном он объединяет предыдущие ответы.
Если вы хотите пойти по пути ручной очистки, есть еще несколько файлов, которые также могут содержать ссылку на позицию вашей исходной ветви перед веткой git-filter-branch. Например, я отфильтровал свою "домашнюю" ветку:
.git / Информация / рефов:
179ad3e725816234a7182476825862e28752746d refs / original / refs / heads / home
.git / уплотненные рефы:
179ad3e725816234a7182476825862e28752746d refs / original / refs / heads / home
После того, как я удалил эти строки, gitk больше не показывал старые коммиты.
Поскольку это старый вопрос, возможно, тогда это было невозможно. Это также предполагает, что вы используете 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
непосредственно в папку, и, в частности, эта команда обрабатывает случай, когда ссылки находятся в packed-refs
,
Вторая и третья строки взяты непосредственно из Как очистить неиспользуемые боковые ветви в ваших деревьях коммитов?,
Ответ на 2021 год
На удивление это оказывается трудной задачей. Google выдает страницы, датированные 2009 годом, и обсуждения StackOverflow почти десятилетней давности. Многие из этих вещей больше не работают!
Вот что работает (также рекомендуется в соответствии с git docs):
Первая установка
git-filter-repo
:
pip install git-filter-repo
Затем удалите папки из истории git. Это перезапишет всю историю Git, кроме исключенной папки!
git filter-repo --force --invert-paths --path to/folder1 --path to/folder
Затем добавьте обратно пульты:
git remote add origin https://...
Затем принудительно протолкните вверх по течению:
git push --force --set-upstream origin master
Итак, это набор команд, но я не нашел более короткого лучшего способа.