Мы планируем применять стиль в формате clang в исходном репозитории. Мы ожидаем некоторых трудностей, поэтому мы хотим предоставить цель make для выполнения переформатирования текущей ветви от ее базы слияния с master до ветви HEAD.
В качестве упрощенного примера рассмотрим следующую команду:
git filter-branch -f --tree-filter '
AFFECTED_FILES=$(git diff-index --diff-filter=AM --name-only $GIT_COMMIT^);
echo; echo AFFECTED $AFFECTED_FILES;
for f in $AFFECTED_FILES; do
echo formatting $f;
echo foo >> $f;
done
' HEAD~10..HEAD
Мы запускаем древовидный фильтр для нескольких коммитов (мы просто ограничиваем это до нескольких последних коммитов, это уже демонстрирует проблему). Мы определяем затронутые файлы (мы только хотим коснуться файлов, добавленных или измененных в коммите). Для простоты (ошибку легче обнаружить), мы не используем здесь формат clang, а просто добавляем «foo» к каждому из этих затронутых файлов (замена echo foo >> $f
на clang-format -i $f
- это все, что необходимо для получения фактического код).
Он правильно применяет изменения, которые мы намереваемся. Однако в каждом, кроме первого коммита, он отбрасывает изменения, которые мы сделали ранее. Просматривая коммиты, предположим, что в файле some.txt вы видите «+ foo» в diff. В дочернем коммите для some.txt вы видите «-foo» в diff, даже если some.txt вообще не был изменен в дочернем коммите, а только someother.txt. Я выполнил это на произвольных тестовых репозиториях, демонстрируя то же поведение.
Я также попробовал следующее (возвращаясь к фактическому формату clang):
git filter-branch -f --tree-filter 'git clang-format --extensions cpp,h' -- HEAD~10..HEAD
Хотя большинство коммитов выглядят правильно, первый из них изменяет все файлы, затронутые любым коммитом в заданном диапазоне. Я хочу избежать этого и форматировать только те файлы, которые были затронуты коммитом.
Чего мне не хватает, чтобы избежать отмены изменений в детских коммитах? Нужно ли каким-либо образом обновлять индекс?