自行承担风险!据我所知,git 过滤器不是为此目的而设计的!
话虽如此,但有一些注意事项是可能的,我将分享一个有效的设置。
先决条件
回购需要使用样式强制工具,如clang-format,可以用作管道。格式和格式化工具需要满足以下属性:如果您从存储库样式格式的文件开始,应用本地格式,然后应用存储库格式,那么您将得到原始文件。
道路
假设存储库样式基于 LLVM 样式,最大行长度修改为 150 个字符,而您更喜欢最大 80 个字符的行。您只想对单个文件 path/file.cc 进行样式转换。从一个干净的存储库状态开始。
使用以下内容创建.git/info/attributes:
path/file.cc filter=style
将以下内容放入.git/config:
[filter "style"]
clean = <path>/upstream-style.sh %f
smudge = <path>/local-style.sh %f
提到的upstream-style.sh脚本有:
#!/bin/bash
<path>/clang-format --verbose --style="{BasedOnStyle: LLVM, ColumnLimit: 150}"
而 local-style.sh 有:
#!/bin/bash
<path>/clang-format --verbose --style="{BasedOnStyle: LLVM, ColumnLimit: 80,
ReflowComments: false}"
这些文件还没有重新格式化,因为没有 git 操作。触发重新格式化的一种简单方法是切换到另一个分支并返回。
注意事项
我们依赖于执行local-style.sh,然后执行upstream-style.sh(或相反),你会得到完全相同的文件。所有样式选项都不能保证这一点。
特别是,cmets 可能是个问题。选项 ReflowComments: false 应该有助于注释块,但内联 cmets 很可能仍然是一个问题。带有内联 cmets 的行比允许的长度长,它可能会被打断并且在转换过程中不会恢复到原来的形式。
如果 cmets 和代码从不在同一行,应该没有问题。顺便说一句,我更喜欢遵循这条准则。 (我喜欢在文件、类、函数的开头使用注释块,而不是散布在函数内部。)
git diff 命令可能不会显示正确的行号。
笔记
脚本接收正在格式化的文件名。但是,调用 clang-format 时使用文件名是错误的。您可能会收到“找不到文件”错误,因为在脚本执行时磁盘可能没有副本。
在脚本中使用名称仍然有用。我用它来向标准错误打印一条消息,例如:
>&2 echo "Formatting $1 for local."
如果出现问题,请注释掉 attributes 文件中的行并重置存储库。
我成功地使用了这个解决方案。我在提交、变基、挑选过程中没有遇到任何问题。