2009-08-01 6 views
48

В моем личном git repo у меня есть каталог, содержащий тысячи небольших изображений, которые больше не нужны. Есть ли способ удалить их из всей истории git? Я попыталсяУдалить каталог навсегда из git

git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch imgs" HEAD 

и

git filter-branch --tree-filter 'rm -fr imgs' HEAD 

но размер мерзавца репо остается неизменным. Есть идеи?

Благодаря

+2

Не уверен, но вы пробовали запустить 'git gc' после? Может быть, они все еще там как мусор ... –

+0

@Martinho: yes Я – adk

+0

Вам придется удалить все старые ссылки (например, названия ветвей, теги), и вы можете запустить git gc -aggressive после этого. – vdboor

ответ

15

На самом деле ни один из этих методов не workedfor меня. я нашел самый надежный был в том, чтобы просто тянуть локально в другой репо:

git pull file://$(pwd)/myGitRepo 

Это также экономит вам хлопот deletig старых тегов.

увидеть историю в моем блоге: http://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/

+0

Это похоже на сделку для меня. Я документировал конкретные шаги Windows здесь: http: //www.somethingorothersoft.com/?p = 80 –

32

ProGit книга имеет интересный раздел Removing Object.

Она не кончается с этим:

Ваша история больше не содержит ссылку на этот файл.
Однако, ваш reflog и новый набор ссылок, которые Git добавил, когда вы делали filter-branch под номером .git/refs/original, все еще делают, поэтому вам нужно удалить их, а затем переупаковать базу данных. Вы должны избавиться от всего, что имеет указатель на старые фиксации, прежде чем репак:

$ rm -Rf .git/refs/original 
$ rm -Rf .git/logs/ 
$ git gc 
$ git prune --expire 

(git prune --expire не является обязательным, но может удалить содержимое каталогов из рыхлых объектов)
резервного копирования все, прежде чем делать эти команды на всякий случай;)

+0

Ссылка на книгу больше не работает :-( – rescdsk

+3

@rescdsk Я восстановил ссылку. – VonC

+0

Awesome, спасибо! – rescdsk

13

git-filter-branch по умолчанию сохраняет старые ссылки в refs/original/* пространства имен.

Вы должны удалить их, а затем сделать git gc --prune=now

3

Если вы хотите пойти ручную очистку маршрут, есть еще несколько файлов, которые могут также содержать реф в положение исходной ветви перед git- фильтр-отделение. Например, я фильтруется свой "домашний" филиал:

.git/Информация/рефов:

179ad3e725816234a7182476825862e28752746d ссылки/оригинал/рефов/головы/дома

.Git/уплотненный рефов:

179ad3e725816234a7182476825862e28752746d рефов/оригинал/ссылки/главы/дома

После я удалил эти строки, gitk не показывают старый совершает больше.

+1

работал для меня, хотя я доволен, если это просто зафиксировало представление gitk или если refs на самом деле будет gc'd сейчас – gravitation

10

Brandon Thomson спросил в комментарии к решению Rainer Blome «s, если это просто исправили вид 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, как показано на Rainer Blome, окончательный

$ git gc --prune=now 

сделано не только рефов, но и старый объекты (коммиты, деревья и капли) уходят. Вышеуказанное значение git ls-tree hash-value подтверждает это. Еще одна приятная команда для проверки этого - git count-objects -v (запустите ее перед фильтровальным захватом и после обрезки и сравните размер).

Примечание: Поскольку мне еще не разрешено комментировать другие ответы, мне пришлось написать новый, хотя в основном он сочетает в себе предыдущие ответы.

+0

Этот ответ * кажется * как правильное решение для меня. Однако я не понимаю, почему общий размер моего репозитория не изменился. – dbn

2

Поскольку это старый вопрос, возможно, в то время это было невозможно. Это также предполагает, что вы используете 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 напрямую, и, в частности, эта команда обрабатывает случай, когда refs находится в packed-refs.

Вторая и третья линии взяты непосредственно с How to clean up unused side-branches in your commit trees?.