Git 将 chmod 改动视为修改是因为默认启用 core.filemode 跟踪可执行位;关闭需设为布尔 false,且已跟踪文件须手动刷新索引或重置权限。

Git 为什么总把 chmod 改动当成修改
因为 Git 默认开启 filemode 跟踪,它会记录文件的可执行位(x 权限)变化。哪怕只是 chmod 644 script.sh → chmod 755 script.sh,Git 就认为这是“内容变更”,git status 里就多出一行修改。这不是 bug,是设计如此——尤其在跨平台协作时(比如 Linux 写完推到 Windows 同事那里),权限语义不一致,Git 宁可保守点。
关闭 filemode 的两种生效范围
全局关掉(推荐给个人开发机):
git config --global core.filemode false
仅当前仓库关掉(适合团队项目,避免影响他人):
git config core.filemode false
注意:core.filemode 是布尔值,不是字符串,别写成 "false" 或 off,否则无效。
- 改完后,已跟踪的文件不会自动“撤销”权限差异,得手动重置:先
git add --chmod=-x <file>或git update-index --chmod=-x <file>,再git commit - 新克隆的仓库默认继承全局配置,但已有仓库不会自动更新,必须显式运行
git config - Windows 和 macOS 上
core.filemode false几乎必开;Linux 服务器若严格依赖权限(如部署脚本),反而要保持true
遇到 git status 还显示权限变更?检查这三处
关了 filemode 还有权限提示,大概率是以下情况之一:
-
git ls-files --stage | grep '^100' | head -3看输出第三列是否为755或644—— 如果仍是旧权限,说明索引没刷新,需git update-index --refresh - 文件被 IDE 或编辑器偷偷改了权限(比如 VS Code 保存时自动加执行位),关掉编辑器的
files.autoSave或检查其权限相关设置 - 用了
git clone --shared或硬链接工作区,底层 inode 权限状态可能被缓存,换普通 clone 试一下
替代方案:用 .gitattributes 强制忽略特定文件类型权限
如果只想忽略脚本类文件的权限(比如所有 .sh、.py),又不想全局关 filemode,可以用 .gitattributes:
*.sh text eol=lf *.py text eol=lf *.sh -exec *.py -exec
其中 -exec 表示“不关心可执行位”,Git 不再将其纳入 diff。但注意:
-
.gitattributes只对新增文件或重新添加的文件生效,已有文件得先git rm --cached <file>再git add <file> - 这个规则不递归覆盖子目录里的同名文件,除非路径写成
**/*.sh - 部分旧版 Git(-exec,会静默忽略,建议先
git check-attr -a <file>验证是否识别
最常被忽略的是:关 filemode 后,如果某天真需要提交权限变更(比如正式发布一个可执行工具),得临时打开它并显式 git update-index --chmod=+x,否则 Git 根本不记录。


















