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

Вторая и третья строки берутся непосредственно из Как очистить неиспользуемые боковые ветки в деревьях коммита?.