项目编码风格的一些元素让我很烦。例如,我更喜欢 80 个字符的行长度,我从不希望 if 的条件和语句在同一行(用于断点放置)等。
我想使用 git 过滤器将代码从上游 repo 转换为我喜欢的格式,在开发过程中使用首选格式,然后在我推送时将其转换回来。
该项目使用 clang-format,因此有一个非常明确的样式。
这能做到吗?
这样做需要您自担风险! 据我所知,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
(或相反)你得到完全相同的文件。所有样式选项都不能保证这一点。
特别是,评论可能是个问题。选项
ReflowComments: false
应该有助于评论块,但行内评论很可能仍然是一个问题。超过允许长度的行内注释行可能会被打断,并且在转换过程中不会恢复到原来的形式。
如果注释和代码从不在同一行,应该没有问题。顺便说一句,我更喜欢遵循这条准则。 (我喜欢在文件、类、函数的开头使用注释块,而不是穿插在函数内部。)
git diff
命令可能不会显示正确的行号。
注意事项
脚本接收正在格式化的文件名。但是,调用 clang-format 时使用文件名是错误的。您可能会收到“找不到文件”错误,因为在脚本执行时磁盘可能没有副本。
脚本中的名称仍然有用。我用它来打印一条消息到标准错误,例如:
>&2 echo "Formatting $1 for local."
如果出现问题,注释掉
attributes
文件中的行并重置存储库。
我成功地使用了这个解决方案。我在 commit、rebase、cherry-pick 期间没有遇到任何问题。