Одним из способов сделать это является обратное - удалить все, кроме файла, который вы хотите сохранить.
По сути, создайте копию хранилища, затем используйте git filter-branch
, чтобы удалить все, кроме файла / папок, которые вы хотите сохранить.
Например, у меня есть проект, из которого я хочу извлечь файл tvnamer.py
в новый репозиторий:
git filter-branch --tree-filter 'for f in *; do if [ $f != "tvnamer.py" ]; then rm -rf $f; fi; done' HEAD
Использует git filter-branch --tree-filter
для прохождения каждого коммита, запуска команды и повторной отправки содержимого каталогов. Это чрезвычайно разрушительно (поэтому вы должны делать это только с копией вашего хранилища!) И может занять некоторое время (около 1 минуты в хранилище с 300 коммитами и около 20 файлами)
Приведенная выше команда просто запускает следующий shell-скрипт для каждой ревизии, который вам, конечно, придется изменить (чтобы исключить ваш подкаталог вместо tvnamer.py
):
for f in *; do
if [ $f != "tvnamer.py" ]; then
rm -rf $f;
fi;
done
Самая большая очевидная проблема заключается в том, что он оставляет все сообщения о коммитах, даже если они не связаны с оставшимся файлом. Сценарий git-remove-empty-commits , исправляет это ..
git filter-branch --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "$@"; else git commit-tree "$@"; fi'
Вам необходимо использовать аргумент -f
force, снова запустить filter-branch
с любым значением в refs/original/
(что в основном является резервной копией)
Конечно, это никогда не будет идеальным, например, если в ваших сообщениях о коммитах упоминаются другие файлы, но он настолько близок, насколько позволяет git current (насколько я знаю в любом случае).
Опять же, запускайте это только для копии вашего репозитория! - но в итоге, чтобы удалить все файлы, кроме "thisismyfilename.txt":
git filter-branch --tree-filter 'for f in *; do if [ $f != "thisismyfilename.txt" ]; then rm -rf $f; fi; done' HEAD
git filter-branch -f --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "$@"; else git commit-tree "$@"; fi'