用 git diff 审 meta 变更,我把 8 万行差异压到了 200 行

我们仓库里每个数据表目录下挂一个 meta.yaml,描述字段类型、脱敏级别、下游依赖。表数量不大,四百多张,但单个 meta 文件平均两百多行——下游依赖那个数组占了大头。问题出在评审阶段:有人改一个字段的脱敏级别,PR 里 diff 显示几百行,因为数组顺序被序列化工具重排了。评审的人看不过来,最后基本是点通过。

我的做法是先把结构稳下来,再让 diff 只暴露语义变化。第一步固定序列化,用 ruamel.yaml 保留顺序,提交前跑一次归一化:

from ruamel.yaml import YAML
import sys

yaml = YAML()
yaml.preserve_quotes = True
yaml.indent(mapping=2, sequence=4, offset=2)

for path in sys.argv[1:]:
    with open(path) as f:
        data = yaml.load(f)
    with open(path, "w") as f:
        yaml.dump(data, f)

第二步更关键:给下游依赖数组加排序键,归一化时按 name 排。这样重排类改动在提交前就被吃掉了,进 PR 的只有真正的新增、删除和值变更。

第三步是评审侧。我在 CI 里加了一步,对 meta 文件单独跑 git diff --word-diff=porcelain,按字段名切块,输出每个变更字段的旧值和新值。四百多张表一次全量改版时,原始 diff 八万多行,这步之后落到两百行左右,评审能在半小时内过完。

为什么这样做:meta 的 diff 噪音来自两个地方,序列化不稳定和集合无序。这两个都不是语义,但会淹没语义。固定序列化和排序是把「表示层」压平,代价是归一化会改写文件,所以得约定归一化必须在提交前跑,不能挂 pre-commit 自动改——自动改会让工作区在 commit 中途变脏,我踩过,git commit -a 直接漏掉了归一化后的内容。

失效的地方得说清楚。排序键只对 name 唯一的数组成立,我们有一张表的下游依赖里出现了同名不同版本的条目,排序后相对顺序不稳定,diff 又开始抖,最后只能给这类数组加 sort: false 的注释标记跳过。另外 word-diff 对多行字符串字段基本没用,脱敏规则描述那种长文本一改还是整段红绿,这部分我放弃自动切块,靠人工看。还有个反例:归一化脚本对 YAML 锚点和别名处理不好,展开后文件变大,我们干脆在仓库规范里禁用了锚点。

现在还剩一个没解决的问题:跨文件的 meta 引用变更,比如一张表改名,所有引用它的 meta 都会变,单个文件的 diff 很干净,但 PR 整体还是几十个文件。你们审这类连锁变更时是按文件看还是先聚合出一张引用图?

0
Approval 100% · 0 comments · 8 Reads

0 comments

Markdown supported · replies push in real time

No comments yet — be the first.