Ответ 1
Каждый аргумент для различных ...-filter
должен быть одной строкой. Эта строка сохраняется как переменная оболочки:
--index-filter)
filter_index="$OPTARG"
;;
В соответствующей точке ветвь фильтра script (найденная в подкаталоге git-core
, например, /usr/libexec/git-core
или /usr/local/libexec/git-core
) делает следующее:
eval "$filter_index" < /dev/null ||
die "index filter failed: $filter_index"
(за исключением фильтра фиксации, который запускается с /bin/sh -c "$filter_commit" ...
).
Ваше предположение, таким образом, является правильным, и вам нужно сделать список файлов частью отдельной строки, разделенной пробелом.
Самый простой способ сделать это - начать с вашей исходной команды:
git filter-branch -f --index-filter \
'git read-tree --empty && git reset -q "${GIT_COMMIT}" -- <list of files>' \
--prune-empty -f
(который работает, когда у вас есть статический список) и измените его, чтобы извлечь динамический список из ~/to_keep.txt
. Я разбил оригинал на три строки частично для показа, но также потому, что теперь мы можем сосредоточиться только на средней линии.
[Изменить для исправления проблемы новой строки, отмеченной в комментарии. Пусть сделайте псевдоним или функцию оболочки, xc
, которая переводит символы новой строки в пробелы]
xc() {
tr '\n' ' '
}
"git read-tree --empty && git reset -q \"\${GIT_COMMIT}\" -- $(xc < ~/to_keep.txt)" \
или
'git read-tree --empty && git reset -q "${GIT_COMMIT}" -- '"$(xc < ~/to_keep.txt)" \
или, как вы пытались (но с одним изменением):
'git read-tree --empty && git reset -q "${GIT_COMMIT}" -- '"$tmp" \
(задав tmp=$(xc < ~/to_keep.txt)
).
Обратите внимание, что ни одна из этих правильных вещей, если какое-либо из имен файлов содержит пробел. Например, предположим, что файл имеет имя a file
(со встроенным пустым). eval
будет разбивать аргументы в пробелах, а команда git reset
получит имена a
и file
как два отдельных аргумента.
Пока у вас нет таких имен файлов, вам не нужно беспокоиться об этом.
Еще одна потенциальная проблема заключается в том, что этот список файлов очень длинный. Вы можете столкнуться с ограничениями ядра на количество аргументов, которые могут быть отправлены в один файл. Вы должны использовать xargs
для решения этой проблемы (и, в этом случае, с некоторой работой и использованием -0
, для обработки белого пространства в именах файлов).