【发布时间】:2018-11-07 09:22:29
【问题描述】:
我们计划在源代码库中实施基于 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-format,而只是将“foo”附加到每个受影响的文件中(将 echo foo >> $f 替换为 clang-format -i $f 是获取实际文件所需的全部内容)代码)。
它确实正确应用了我们想要的更改。但是,在除第一次提交之外的每个提交中,它都会丢弃我们之前所做的更改。查看提交,假设在文件 some.txt 中您在 diff 中看到“+foo”。在子提交中,对于 some.txt,您会在 diff 中看到“-foo”,即使在子提交中根本没有修改 some.txt,而只是修改了 someother.txt。我已经在任意测试存储库上运行它,显示相同的行为。
我还尝试了以下方法(回到实际的 clang 格式):
git filter-branch -f --tree-filter 'git clang-format --extensions cpp,h' -- HEAD~10..HEAD
虽然大多数提交看起来确实正确,但第一个提交将修改给定范围内的任何提交所触及的所有文件。我想避免这种情况,并且只格式化提交所触及的文件。
为了避免撤销子提交中的更改,我缺少什么?我需要以某种方式更新索引吗?
【问题讨论】:
-
您可以添加您的解决方案作为您自己问题的答案。 :)
标签: git git-filter-branch git-rewrite-history