2017-02-15 2 views
0

Большинство примеров фильтров-фильтров git Я видел, что удаление файлов было для удаления файлов на основе filename. Я не хочу этого делать. Вместо этого я определил несколько SHA1-ов из файлов, которые я хочу удалить, независимо от того, где они находятся в репозитории. (Из-за нашей истории репо, файлы, как правило, перемещаются вокруг группы, не меняя.)Как использовать git filter-branch для удаления файла с помощью blob SHA1?

Что можно сказать git filter-branch для удаления файлов на основе их blob SHA1?

+2

Если вы можете использовать очиститель репозитория BFG, он имеет простую поддержку для этой операции и намного быстрее, чем использование ветви фильтра –

ответ

4

Ваша задача - удалить капли из истории Git хеш-идентификатором. Вы можете найти его быстрее и проще в использовании BFG, а не git-filter-branch, в частности, с использованием --strip-blobs-with-ids флага:

-bi, --strip-сгустки-с-идентификаторами <blob-ids-file> ... полосой с узором водных потеков указанным Git объектные идентификаторы

Тщательно следуйте usage instructions, основная часть всего этого:

$ java -jar bfg.jar --strip-blobs-with-ids <blob-ids-file> my-repo.git 

Обратите внимание, что файл <blob-ids-file> должны сотрудничать Идентификаторы объектов Git, а также простые хэши SHA-1 содержимого blob.

Для данного файла, можно вычислить идентификатор объекта Git с git hash-object:

$ git hash-object README.md 
a63b49c2e93788cd71c81015818307c7b70963bf 

Вы можете видеть, что это значение отличается от простого SHA-1 хеш:

$ sha1sum README.md 
7b833f7b37550e2df719b57e8c4994c93a865aa9 README.md 

. Это связано с тем, что идентификатор объекта Git хэширует заголовок Git вместе с содержимым файла, хотя он использует один и тот же алгоритм SHA-1.

BFG обычно не менее чем на 10-50 раз быстрее, чем работает git-filter-branch и, как правило, проще в использовании.

Полное раскрытие информации: Я являюсь автором BFG Repo-Cleaner.

+0

. Я думаю, что здесь не упоминается: по умолчанию BFG не будет удалять из голова совершает, не так ли? Поэтому, если вы хотите удалить * все * экземпляры blob, вы должны отключить это ... –

+1

Это правда, вы можете отключить это с помощью '--no-blob-protection'. Моя рекомендация с репозиторием в реальном времени всегда заключалась бы в том, чтобы вручную исправить ваше текущее дерево файлов и обеспечить все, что все еще работает, - прежде чем переписывать историю. Мне гораздо лучше, если люди не используют мой инструмент для разрыва их производственных систем! https://rtyley.github.io/bfg-repo-cleaner/#protected-commits –

+0

lol Я заметил ваше отвращение к использованию '--no-blob-protection'; для чего это стоит, так как переписывать (ну, должно быть) сделано на зеркальном клоне в любом случае, если он ломается, мы просто не нажимаем его на оригинал, так что никакого реального вреда не делается –

0

версия фильтра филиал может выглядеть как эти внутри индекс фильтра:

git ls-files -s | 
    sed -r '/ 02c97746d64fbfe13007a1ab4e9b9e4bbd99f42f /s/^100(644|755)/0/' | 
    git update-index --index-info 

То есть, читать формат индекс информации, найти интересную блоб и установить режим 0 (маркировку он для удаления), затем напишите это обратно к индексу.

+1

Хотя я по-прежнему рекомендую использовать BFG, я должен восхищаться этим ответом для чистой выродки chutzpah: heart : –

+0

Я считаю, что это нужно было бы сделать как фильтр дерева, что сделало бы его еще медленнее, чем намеченный подход на основе фильтра индекса. Но это расщепление волос; BFG - лучший инструмент для этой работы. –

0

Как отметил @RobertTyley в своем ответе, вам, вероятно, лучше использовать BFG. Тем не менее, чтобы ответить на заданный вопрос (как это сделать с filter-branch):

К сожалению, к сожалению, нет никакого отличного способа. Вы можете написать скрипт, чтобы получить все имена файлов, связанные с значением SHA в индексе. В качестве отправной точки, если вы удаляете файл с хэш-DEADC0DE

git rev-list -n 1 --objects HEAD |grep ^DEADC0DE |cut -c 42- 

Вы бы затем кормить каждую строку (возможно, с xargs?) Как <filename> в

git rm --cached <filename> 

И вы будете использовать этот сценарий как ваш index-filter значения (так как использовать его в качестве дерева фильтра будет просто сделать уже медленный подход еще медленнее).

0

git filter branch --index-filter помещает итеративно каждую фиксацию в индекс, чтобы можно было восстановить имя файла из хэша с помощью git ls-files -s.

Я делаю это, чтобы удалить сгустки с хэши 2d341f0223ff, 6a4558fa76d1 и 4d0a90cba061:

git filter-branch --force --index-filter "git ls-files -cdmo -s | grep ' 2d341f0223ff\| 6a4558fa76d1\| 4d0a90cba061' | awk '{print $4}' | xargs git rm --cached --ignore-unmatch 656565randomstring546464" --prune-empty --tag-name-filter cat -- --all

случайная строка, чтобы избежать этого git rm вызывает ошибку, когда grep возвращается не совпадают.

Смежные вопросы