Это основано на примере в странице-ветке фильтра :
git filter-branch --index-filter 'git ls-files -s | grep $'\t'<file-to-keep>$ | \
GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && \
mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' --prune-empty -- --all
Фильтр индекса печатает текущее содержимое индекса с помощью git ls-files -s
, выдает толькофайл для хранения (этот grep довольно навязчивый - поля разделены табуляцией, а имя файла - последним), затем создает новый индекс, используя эту информацию, и перемещает его поверх старого.
Опция --prune-empty
заставляет filter-branch удалять любые коммиты, которые теперь ничего не делают (т. Е. Они только касались других файлов), а -- --all
говорит ему переписать все ссылки.
Как всегда с filter-ветвь, лучше всего сделать это в новом клоне, так что если вы действительно что-то испортили, вы в безопасности, хотя filter-branch сохраняет резервные копии в ссылках / оригиналах.Вы также можете прочитать контрольный список для сокращения хранилища на странице руководства;В результате, как только вы закончите, лучший способ избавиться от всего, что вам больше не нужно, - просто клонировать отфильтрованный репозиторий.
Это на самом деле будет работать, даже если файл был изменен вте же самые коммиты, что и в других файлах, хотя я полагаю, что вы можете попытаться быть хитрым и воспользоваться этим фактом, просто сгенерировав патчи для всех коммитов, которые коснулись этого файла *, затем перейдите и создайте новый репозиторий, применивэти патчи ... но зачем?
(Примечание: гораздо проще удалить отдельный файл, чем сохранить один файл. Все, что вам нужнов этом случае используйте git rm --cached --ignore-unmatch <filename>
для индексного фильтра.)