Удалить каталог навсегда из 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

Итак, это набор команд, но я не нашел более короткого лучшего способа.

Другие вопросы по тегам