Git 内容没变却出现 modified:core.fileMode 与脚本执行位
先确认 diff 只有模式变化,再按仓库设置 fileMode;关闭检测后显式核对和记录脚本在暂存区的可执行模式。
代码内容没有改动,Git 却把很多文件标成 modified;git diff 只显示 old mode 100644、new mode 100755。仓库从 Linux 文件系统转到共享挂载,或同一目录被 Cygwin 和其他 Git 实现交替访问时,应检查可执行位是否被运行环境改变。
core.fileMode=false 可以忽略工作树可执行位差异,但也会影响之后怎样记录脚本权限。先确认确实只有模式变化,再决定是否在这个仓库设置它。
先分清模式变化与内容变化
在仓库内检查下面这些只读信息,scripts/run.sh 是待检查文件的占位路径:
git diff --summary
git diff -- scripts/run.sh
git diff --cached -- scripts/run.sh
git config --show-origin --get core.fileMode
git ls-files --stage -- scripts/run.sh
普通 git diff 比较工作树与暂存区,--cached 比较暂存区与当前提交。两边都要检查,避免把已经暂存的内容修改漏掉。
下面只是纯模式差异的示例:
old mode 100644
new mode 100755
对普通文件而言,Git 的这两种模式主要区别是是否可执行;它不按原样记录所有 Unix 读写权限。若 diff 同时有文本内容、换行或文件类型变化,应分别处理;关闭 core.fileMode 不会隐藏这些变化。
只在可执行位不可靠的仓库关闭检测
Git 在 clone 或 init 时会探测文件系统。后来换了访问环境,原先正确的设置可能不再适合当前工作树。如果确认环境无法可靠保留可执行位,可以仅为这个仓库设置:
git config --local core.fileMode false
它让 Git 判断工作树变化时忽略可执行位,并不执行 chmod,也不会抹掉提交和暂存区里已经记录的可执行模式。修改前记录配置来自哪里、仓库本地是否已有该值;需要恢复时还原原本的本地设置,原本没有本地值就移除本次新增项,让原有配置层级继续生效。
不要为了清理一个共享目录的噪声,把这个设置全局应用到所有仓库。正常保留 Unix 权限的工作树,可能需要及时发现脚本失去执行位。
之后新增脚本,要明确记录执行模式
关闭检测后,不能只在磁盘上 chmod +x,再假定 git add 一定会把新脚本存成可执行。应检查暂存区实际模式。对已经进入暂存区、确实需要直接执行的普通文件,可显式设置:
git update-index --chmod=+x -- scripts/run.sh
git diff --cached --summary
git ls-files --stage -- scripts/run.sh
第一条会修改暂存区,使用前先确认文件已经由 Git 跟踪,并核对暂存区内是否有其他待提交工作。需要提交执行位时,应看到对应文件的模式变为 100755;只是读取数据的文件不应加执行位。
如果本次设置错误,应仅把这个文件的暂存模式恢复为之前记录的值,不要用整仓库重置去清理。这个命令处理的是 Git 记录,当前机器是否允许直接执行文件仍由文件系统、挂载和操作系统权限决定。
检查最终提交,而不是只看 status 变干净
合理结果是无意产生的模式噪声消失,真实内容变化仍然可见;需要执行的脚本在暂存区和最终提交中保留正确模式。提交后可查看目标脚本:
git ls-tree HEAD -- scripts/run.sh
工作树 status 干净,只说明当前比较规则没有发现未提交差异。它不能代替对脚本模式的核对,也不能证明部署机器上的执行权限已经正确。


