新克隆Git仓库切换分支后显示未暂存变更的排查求助
我之前也碰到过一模一样的情况!看你贴出的git diff输出,有两个关键线索能帮我们定位原因:文件权限从100644变成100755,还有文件里出现了^M(Windows系统的CRLF换行符标记)。下面一步步拆解调试方法和可能的原因:
可能的原因
1. Git默认追踪文件权限变化
Git默认会监控文件的执行权限变更,如果你的两个分支(master和pollers-1.0)对share/mibs/IANAifType-MIB.mib设置了不同的权限,切换分支时Git就会把这个权限差异当成工作区的修改。
2. 换行符自动转换配置冲突
^M是Windows的CRLF换行符,而你用的是macOS(从终端提示符能看出来),默认用LF换行符。如果你的Git开了core.autocrlf自动转换功能,当不同分支的文件用了不同换行符时,切换分支后Git会自动转换换行符,导致工作区文件和当前分支的HEAD版本不一致,显示为未暂存变更。
调试与解决步骤
第一步:确认权限差异是否是预期的
先查两个分支里该文件的权限,验证是不是分支本身就有不同设置:
# 查看master分支中该文件的权限 git ls-tree master -- share/mibs/IANAifType-MIB.mib # 查看pollers-1.0分支中该文件的权限 git ls-tree pollers-1.0 -- share/mibs/IANAifType-MIB.mib
如果确实是分支间的权限差异,而你不需要Git追踪权限变化,可以关闭这个功能:
# 仅当前仓库生效 git config core.filemode false # 如果想全局所有仓库都生效,加--global参数 git config --global core.filemode false
第二步:排查换行符转换问题
先看当前的换行符配置:
git config core.autocrlf
- 输出
true:Git会自动把LF转换成CRLF(Windows常用) - 输出
input:Git会把CRLF转换成LF(Linux/macOS常用) - 输出
false:不做任何换行符转换
你可以先临时禁用自动转换来验证:
git config core.autocrlf false # 重置工作区的该文件 git checkout -- share/mibs/IANAifType-MIB.mib # 再看状态 git status
如果此时git status显示工作区干净了,说明就是换行符转换的问题。推荐在仓库根目录添加.gitattributes文件统一管理换行符规则,比如强制所有.mib文件用LF:
# .gitattributes 内容 *.mib text eol=lf
第三步:检查是否有真实内容差异
有时候权限和换行符的变化会掩盖真实的文件内容修改,你可以用忽略这些差异的diff命令查看:
# 忽略权限变化的diff git diff --no-filemode # 忽略换行符变化的diff git diff --ignore-cr-at-eol # 同时忽略两者 git diff --no-filemode --ignore-cr-at-eol
如果这样diff后还有内容差异,那就是文件确实有修改,需要确认是否是预期的变更。
总结
这种切换分支后莫名出现的未暂存变更,90%以上都是Git的权限追踪或换行符自动转换导致的,按照上面的步骤排查,基本能快速定位并解决问题。
内容的提问来源于stack exchange,提问作者Dimitar Petrov

