Это основано на примере на странице руководства filter-branch:
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-branch, лучше всего сделать это в свежем клоне, поэтому, если вы что-то сильно испортите, вы в безопасности, даже если filter-branch действительно хранит резервные копии в refs / originals. Вы также можете прочитать контрольный список для сжатия репозитория на странице руководства. ; В результате лучший способ избавиться от всего, что вам больше не нужно, - это просто клонировать отфильтрованный репозиторий.
Это действительно сработает, даже если файл был изменен в тех же коммитах, что и другие файлы, хотя я полагаю, вы могли бы попытаться скрытно воспользоваться этим фактом, просто сгенерировав патчи для всех коммитов, которые действительно коснулись этот файл, а затем создать новый репозиторий, применив эти исправления ... но зачем беспокоиться?
(Примечание: проще удалить отдельный файл, чем сохранить отдельный файл. Все, что вам нужно сделать в этом случае, - это использовать git rm --cached --ignore-unmatch <filename>
для фильтра индекса.)
person
Cascabel
schedule
21.02.2011