Git 改名检测:同一份暂存变化,为什么调高阈值就变成删除和新增

10-01 3阅读

评审页面显示某文件改名了,换一个命令却显示旧文件被删除、新文件被添加。两次查看的是同一份暂存内容,究竟哪一个错了?可以先排除一种直觉:Git 并没有在每次提交里保存一条独立的“移动文件”命令。

差异计算可以根据旧路径消失、新路径出现以及内容相似程度,将一对变化解释为改名。这种解释帮助人阅读补丁,也受选项和候选范围影响。我们用同一份暂存区做三次对照,不在中间修改文件,就能看出展示与存储的区别。

只创建自己的临时仓库

把代码存为 demo.sh,用 bash demo.sh 运行。本文验证环境为 Git 2.52.0 与 Bash 5.2.37。脚本自行建立并清理临时目录;作者身份只通过单条命令参数提供,不写用户全局配置,也不依赖现有仓库。

Git 改名检测:同一份暂存变化,为什么调高阈值就变成删除和新增

AI概念示意图:表现本文的抽象关系,并非软件截图或真实运行结果。

set -euo pipefail
work=$(mktemp -d)
trap 'rm -rf -- "$work"' EXIT
cd "$work"
git init -q
for ((i=1; i<=20; i++)); do
  printf 'line-%02d stable content\n' "$i"
done > old.txt
git add old.txt
git -c user.name=Demo -c user.email=demo@example.invalid \
  -c commit.gpgsign=false commit -qm base
mv old.txt new.txt
printf 'one extra line\n' >> new.txt
git add -A
without=$(git diff --cached --no-renames --name-status)
loose=$(git diff --cached --find-renames=50% --name-status)
strict=$(git diff --cached --find-renames=100% --name-status)
[[ "$without" == $'A\tnew.txt\nD\told.txt' ]]
[[ "$loose" =~ ^R[0-9]+$'\t'old.txt$'\t'new.txt$ ]]
[[ "$strict" == "$without" ]]
printf 'disabled:\n%s\n50%%:\n%s\n100%%:\n%s\n' \
  "$without" "$loose" "$strict"
printf 'rename checks passed\n'

改变阈值,并没有改变暂存内容

实测关闭检测时出现 A new.txt 与 D old.txt,百分之五十阈值时显示 R096 old.txt new.txt,百分之百阈值又回到新增和删除。实际输出用制表符分隔。断言只要求中间结果属于改名,不把九十六这个具体评分当成跨版本必须不变的接口。

新增一行后,两份内容高度相似,但已经不是完全相同。百分之百阈值要求精确匹配,自然不会把这一对归为改名。实验连续读取同一个暂存区,因此结果变化只能归于差异选项,不能解释为文件又被偷偷改了一次。

这里使用 mv 而不是 git mv,仍然能得到改名展示。因为最终的比较对象是旧快照与暂存快照,平时用哪个命令移动文件并不能成为永久的路径身份记录。git mv 的便利主要在于连同暂存状态一起处理。

评分不是业务上的“相同文件”保证

相似度用于判断内容保留程度,不表示文件用途相同,也不保证程序行为没变。少量配置改动就可能产生重大影响,而大规模格式调整也可能不改变行为。阅读 R 后面的数字时,仍要展开补丁审查关键行。

如果大量文件同时删除和新增,候选配对会更复杂,也可能受到检测限制影响。一个项目设置下能显示改名,另一个环境不显示,并不能立即推断有人丢失历史。先记录实际命令、阈值与配置,再在相同端点重复比较。

也不要把检测阈值当成修复仓库内容的开关。调整它只会改变本次比较的解释,不能恢复误删内容。需要找回文件时,应回到明确的提交或备份;需要审查移动时,则可在暂存前后分别查看路径和实际内容。

提交重排文件的工作时,可以尽量将纯移动与大量内容改写拆成容易理解的步骤,帮助评审者追踪变化,但这只是协作安排。验收标准仍是最终文件是否正确,而不是某个平台必须画出一条改名箭头。

脚本使用 --cached 明确比较暂存区与当前提交。若漏掉它,普通 git diff 会检查工作区与暂存区,而本例工作区已全部暂存,可能什么都看不到。比较端点与检测阈值是两组独立设置,排查时需要同时记录。

参考资料

文章版权声明:除非注明,否则均为云鹊BLOG原创文章,转载或复制请以超链接形式并注明出处。