如何在某个提交后应用静态分析规则
How to apply static analysis rules after a certain commit
我继承了一个需要大量重构的大型项目。我想添加静态分析方法来关注质量。
因为我不想让它们应用 atm/right ,我想知道如何在 Maven 循环中仅对特定提交后创建的文件应用此类规则(如 pmd、findbugs、checkstyle ...) / 时间戳。
谢谢
我无法解决任何 Maven 方面的问题,但是 "files created after some commit" 的一般概念存在一个相当明显的问题,即:每个 Git 提交都是其自身的完整快照。您将如何判断哪些文件是何时创建的?
血统测试
判断某个提交(通过哈希 ID 或任何其他标识符)是否是某个其他提交的 后代 相对容易:
git merge-base --is-ancestor 8ac9f31 33071ac
告诉您提交图中是否由 8ac9f31
"comes before" 33071ac
标识的提交。对于这种事情,使用标签名称可能是明智的(轻量级或带注释的,从使用的角度来看这并不重要)。假设您将此标记命名为 "enable-static-analysis",并希望测试来自名为 $branch
的分支的某些分支提示提交是否在该点之后:
if git merge-base --is-ancestor enable-static-analysis $branch; then
... run static analysis software ...
fi
为了这个特定的目的,测试实际上是 ≤
而不是 <
,也就是说,如果你用 8ac9f31 8ac9f31
重复它,答案将是 "yes, 8ac9f31
is an ancestor of 8ac9f31
. If you need an exclusive less-than property, you can add " 和不等于”,例如:
if git merge-base --is-ancestor enable-static-analysis $branch &&
[ $(git rev-parse enable-static-analysis) != $(git rev-parse $branch) ]; then
或者,如果标记适用于普通的单亲提交,则在测试中使用它自己的直接祖先(这不太明显但效率更高):
# We do not want to run this on a newly created branch whose
# current commit *is* the static-analysis enablement commit,
# hence the hat suffix:
if git merge-base --is-ancestor enable-static-analysis^ $branch
但这只会让你得到 "commit comes after" 部分,而不是 "files created since" 部分。
快照问题
从根本上说,问题是您无法知道提交 $descendant
中的文件 path/to/file.ext
是否与提交 $ancestor
中的文件 path/to/file.ext
有任何关系。此外,如果 $descendant
中的 path/to/file.ext
通过从 some/other/file.ext
或 path/to/othername.otherext
重命名(有或没有任何修改)到达那里怎么办?
实际上,Git 也没有。默认情况下,Git 为 git diff
目的所做的是 假设 这两个文件是 "same entity" 如果它们具有相同的路径名,除非你使用 -B
标志来 git diff
。同时,如果某些路径名在祖先中为 missing,而其他一些路径名在后代中为 new,则该路径对成为候选路径重命名检测。重命名检测基于相似性索引进行工作。如果添加 -B
选项,那么在有问题的两个提交中,具有 相同 路径名的两个文件是 "broken apart" 如果相同的相似性指数低于某些临界点。如果打开重命名检测,任何未配对的文件——包括由于 -B
导致的配对中断的任何文件——都将通过重命名相似性测试 运行,如果它们通过,则将两条路径连接起来作为 "renamed file"。您可以通过 运行ning git diff-tree -r -M --name-status $ancestor $descendant
找到 Git 对此的决定并解析其输出(如果以编程方式执行此操作,也可以考虑添加 -z
)。
这取决于你是要这么花哨,还是以不同的方式花哨(可能的方式主要受限于你的想象力,以及你愿意为此投入多少计算资源;maven 本身可能提供更多方式,特别是如果它有 "manifest" 个文件)。或者您可以使用简单但显然有些缺陷的 "did the path name exist before" 测试来确定 path/to/file.ext
是否是 "created since" 祖先提交:
oldhash=$(git rev-parse --verify --quiet $ancestor:$path)
如果成功,则该路径之前确实存在,并且您现在在 $oldhash
中拥有 blob 的哈希 ID。这会让你知道文件是否已经改变:如果是这样,它从解析 $descendant:$path
作为修订说明符的新散列将不同。
(除了重命名问题,如果 $path
存在于 $ancestor
中,但在某些中间提交中被完全删除,然后在后代提交中或之前重新创建,这显然会失败。这种情况 是 可检测的,通过从 `git rev-list --ancestry-path $ancestor..$descendant 遍历祖先路径中的每个提交,除了你会在祖先路径 DAGlet(子图)中的分支合并结构的情况下,需要注意任何合并。这可能不值得做:Git 的相似性测试可能更可靠。)
如果将所有这些放在一起,您最终可能会想做:
git diff-tree -r --name-status $ancestor $descendant
也许还有一些额外的 --diff-filter
and/or -M
and/or -B
标志。任何状态为 A
(已添加)的文件都将是要分析的文件。状态为 M
的文件也可能是不错的候选者:有人接触过它们,所以是时候让它们通过静态分析了。
我继承了一个需要大量重构的大型项目。我想添加静态分析方法来关注质量。 因为我不想让它们应用 atm/right ,我想知道如何在 Maven 循环中仅对特定提交后创建的文件应用此类规则(如 pmd、findbugs、checkstyle ...) / 时间戳。
谢谢
我无法解决任何 Maven 方面的问题,但是 "files created after some commit" 的一般概念存在一个相当明显的问题,即:每个 Git 提交都是其自身的完整快照。您将如何判断哪些文件是何时创建的?
血统测试
判断某个提交(通过哈希 ID 或任何其他标识符)是否是某个其他提交的 后代 相对容易:
git merge-base --is-ancestor 8ac9f31 33071ac
告诉您提交图中是否由 8ac9f31
"comes before" 33071ac
标识的提交。对于这种事情,使用标签名称可能是明智的(轻量级或带注释的,从使用的角度来看这并不重要)。假设您将此标记命名为 "enable-static-analysis",并希望测试来自名为 $branch
的分支的某些分支提示提交是否在该点之后:
if git merge-base --is-ancestor enable-static-analysis $branch; then
... run static analysis software ...
fi
为了这个特定的目的,测试实际上是 ≤
而不是 <
,也就是说,如果你用 8ac9f31 8ac9f31
重复它,答案将是 "yes, 8ac9f31
is an ancestor of 8ac9f31
. If you need an exclusive less-than property, you can add " 和不等于”,例如:
if git merge-base --is-ancestor enable-static-analysis $branch &&
[ $(git rev-parse enable-static-analysis) != $(git rev-parse $branch) ]; then
或者,如果标记适用于普通的单亲提交,则在测试中使用它自己的直接祖先(这不太明显但效率更高):
# We do not want to run this on a newly created branch whose
# current commit *is* the static-analysis enablement commit,
# hence the hat suffix:
if git merge-base --is-ancestor enable-static-analysis^ $branch
但这只会让你得到 "commit comes after" 部分,而不是 "files created since" 部分。
快照问题
从根本上说,问题是您无法知道提交 $descendant
中的文件 path/to/file.ext
是否与提交 $ancestor
中的文件 path/to/file.ext
有任何关系。此外,如果 $descendant
中的 path/to/file.ext
通过从 some/other/file.ext
或 path/to/othername.otherext
重命名(有或没有任何修改)到达那里怎么办?
实际上,Git 也没有。默认情况下,Git 为 git diff
目的所做的是 假设 这两个文件是 "same entity" 如果它们具有相同的路径名,除非你使用 -B
标志来 git diff
。同时,如果某些路径名在祖先中为 missing,而其他一些路径名在后代中为 new,则该路径对成为候选路径重命名检测。重命名检测基于相似性索引进行工作。如果添加 -B
选项,那么在有问题的两个提交中,具有 相同 路径名的两个文件是 "broken apart" 如果相同的相似性指数低于某些临界点。如果打开重命名检测,任何未配对的文件——包括由于 -B
导致的配对中断的任何文件——都将通过重命名相似性测试 运行,如果它们通过,则将两条路径连接起来作为 "renamed file"。您可以通过 运行ning git diff-tree -r -M --name-status $ancestor $descendant
找到 Git 对此的决定并解析其输出(如果以编程方式执行此操作,也可以考虑添加 -z
)。
这取决于你是要这么花哨,还是以不同的方式花哨(可能的方式主要受限于你的想象力,以及你愿意为此投入多少计算资源;maven 本身可能提供更多方式,特别是如果它有 "manifest" 个文件)。或者您可以使用简单但显然有些缺陷的 "did the path name exist before" 测试来确定 path/to/file.ext
是否是 "created since" 祖先提交:
oldhash=$(git rev-parse --verify --quiet $ancestor:$path)
如果成功,则该路径之前确实存在,并且您现在在 $oldhash
中拥有 blob 的哈希 ID。这会让你知道文件是否已经改变:如果是这样,它从解析 $descendant:$path
作为修订说明符的新散列将不同。
(除了重命名问题,如果 $path
存在于 $ancestor
中,但在某些中间提交中被完全删除,然后在后代提交中或之前重新创建,这显然会失败。这种情况 是 可检测的,通过从 `git rev-list --ancestry-path $ancestor..$descendant 遍历祖先路径中的每个提交,除了你会在祖先路径 DAGlet(子图)中的分支合并结构的情况下,需要注意任何合并。这可能不值得做:Git 的相似性测试可能更可靠。)
如果将所有这些放在一起,您最终可能会想做:
git diff-tree -r --name-status $ancestor $descendant
也许还有一些额外的 --diff-filter
and/or -M
and/or -B
标志。任何状态为 A
(已添加)的文件都将是要分析的文件。状态为 M
的文件也可能是不错的候选者:有人接触过它们,所以是时候让它们通过静态分析了。