Git diff --check:提交前分别检查工作区与暂存区空白错误
文件改干净了,为什么提交里还有空格
编辑器显示的文件内容和下一次提交准备采用的内容可能不同。一个常见过程是先暂存,再删掉行尾空格,最后直接提交。编辑器里确实已经修好,但暂存区仍保留旧版本。排查时若只检查当前磁盘文件,就会把通过检查的对象认错。需要先确定我们要验收的是尚未暂存的修改,还是已经准备提交的修改。
Git 官方说明:不带 --cached 的 diff 比较工作区与暂存区;带 --cached 则比较暂存区与指定提交,通常为 HEAD,--staged 是同义选项。--check 检查新增变更里的空白问题与冲突标记,发现问题返回非零,空白规则受 core.whitespace 控制,不能与 --exit-code 合用。它不是“有差异即失败”的通用判定。
AI生成概念示意图,非真实界面
构造两个位置不同的行尾空格
下面需要 Bash 和 Git,请在准备好的实验目录运行,所有写入都在当前目录下新建的实验仓库。第一行是基线,第二行先写入两个尾随空格并暂存,第三行再写入一个尾随空格但暂不暂存。printf 明确构造空格,避免复制教程时编辑器自动清理,导致错误样本消失。仓库使用演示身份创建本地基线提交,没有任何推送操作。
set -eu
export LC_ALL=C
export GIT_CONFIG_NOSYSTEM=1
export GIT_CONFIG_GLOBAL=/dev/null
base=.
repo=$(mktemp -d "$base/git-check.XXXXXX")
git init -q "$repo"
cd "$repo"
git config core.whitespace trailing-space,space-before-tab
printf 'base\n' > demo.txt
git add demo.txt
git -c user.name=Demo -c user.email=demo@example.invalid \
-c commit.gpgsign=false commit -qm baseline
printf 'base\nstaged bad \n' > demo.txt
git add demo.txt
printf 'base\nstaged bad \nwork bad \n' > demo.txt
check() {
label=$1
expected=$2
shift 2
if git -c color.ui=false diff "$@" --check -- demo.txt; then
result=clean
else
result=problem
fi
printf '%s: %s\n' "$label" "$result"
test "$result" = "$expected"
}
check unstaged problem
check staged problem --cached
printf 'base\nstaged bad\nwork bad\n' > demo.txt
check fixed_worktree clean
check still_staged problem --cached
git add demo.txt
check staged_after_add clean --cached第一次检查应定位 demo.txt 的第三行;第二次带 --cached,应定位第二行。两次都报告 problem,但覆盖的是不同修改。函数没有假定错误退出码一定是哪一个整数,只按是否为零分类;若自己的环境输出与示例不同,先阅读前面的诊断消息,再核对 Git 配置和文件内容,不要直接把所有非零都当成同一种空格错误。
修复工作区之后还要更新暂存内容
第二次 printf 同时修好两处空格。此时 fixed_worktree 应为 clean,而 still_staged 仍为 problem。原因可以直接从操作顺序看出:写文件没有执行暂存。最后再次 git add,staged_after_add 才变为 clean。
在真实项目中,不要照搬示例里的整文件暂存去覆盖已有的精细选择。如果某个文件只打算提交一部分修改,应先检查暂存补丁,按需要重新选择相应片段,再执行暂存区检查。否则虽然空格修好了,却可能顺便把另一项尚未完成的工作带进提交。格式检查通过和提交范围正确,应该分别验收。
把检查放到团队真正使用的边界
对本地待提交内容,重点看暂存区;对代码审查中的提交,则先约定明确的比较起点与终点。不要把当前工作区没有告警误写成整条分支历史都合格。新建而未被跟踪的文件也不会自动成为普通 diff 的检查对象。示例先执行 git add,正是为了让每条待检查内容进入明确的比较关系。
空白规则还需要尊重文件语义。例如某些文本约定会使用行尾空格表达含义,机械删除可能改动内容。团队应先把哪些目录、哪些文件适用什么规则讲清楚,再决定是否阻止提交。无输出且返回零只能证明这次比较没有触发所选规则,不能证明语法正确、测试通过或代码已经完成审查。
逐项核对五个标签:problem、problem、clean、problem、clean,且前两次告警分别对应第三行和第二行。
提交前同时看补丁和检查结果,确认修复内容确实进入暂存区。
若用于自动流程,保留原始诊断输出,让失败能定位到文件和行号。


