经常遇到的问题:
1. 在服务器中修改了项目的文件权限 -> 导致文件发生变更,需要提交,其实文件内容没有任何变化。
2. 将win的项目提交到服务器中 -> 因为换行符不一致,导致文件发生变更,需要提交,其实文件内容没有任何变化。
如何解决这两个问题?
这两个问题都是 Git 中常见的"伪变更"问题,可以通过 Git 的配置来解决:
问题 1:文件权限变更导致 Git 检测到变更
原因
Linux 文件系统会记录文件的可执行权限(
chmod +x 或 chmod 777 等),Git 默认会追踪这些权限变化。解决方案:忽略文件权限变化
bash
复制
# 全局配置(推荐)
git config --global core.filemode false
# 仅当前仓库配置
git config core.filemode false如果已经提交了权限变更,想撤销
bash
复制
# 重置所有文件的权限变更(保留内容变更)
git diff -p -R --no-color | grep -E "^(diff|--git|+++|---)" | grep -v "old mode" | git apply
# 或者更简单地,直接重置暂存区
git reset --hard HEAD # 注意:这会丢弃所有未提交的变更问题 2:换行符不一致(LF vs CRLF)
原因
- Windows:默认使用
CRLF(\r\n) - Linux/macOS:默认使用
LF(\n)
Git 默认会转换换行符,导致跨平台协作时出现"内容相同但换行符不同"的变更。
解决方案:统一换行符配置
推荐方案:仓库统一使用 LF
bash
复制
# 提交时自动将 CRLF 转为 LF,检出时不转换(适合服务器/Linux 环境)
git config --global core.autocrlf input
# 提交时自动将 CRLF 转为 LF,检出时自动转为 CRLF(适合 Windows 开发)
git config --global core.autocrlf true更优雅的方案:使用 .gitattributes(推荐,团队协作必备)
在项目根目录创建
.gitattributes 文件,强制统一换行符:gitattributes
复制
# 自动处理换行符
* text=auto eol=lf
# 特定文件类型强制使用 LF
*.js text eol=lf
*.ts text eol=lf
*.json text eol=lf
*.css text eol=lf
*.html text eol=lf
*.md text eol=lf
*.sh text eol=lf
*.py text eol=lf
# 二进制文件不处理换行符
*.png binary
*.jpg binary
*.gif binary
*.ico binary
*.pdf binary
*.zip binary
*.exe binary然后执行:
bash
复制
# 刷新 Git 的属性处理,重新规范化所有文件
git add --renormalize .
git commit -m "Normalize line endings to LF"如果已经存在换行符混乱,想批量修复
bash
复制
# 安装 dos2unix 工具
# Ubuntu/Debian
sudo apt-get install dos2unix
# macOS
brew install dos2unix
# 批量转换项目中的所有文本文件
find . -type f -not -path "./.git/*" -exec dos2unix {} \;总结对比
表格
| 问题 | 配置项 | 作用范围 |
|---|---|---|
| 权限变更 | core.filemode false | 忽略 chmod 导致的变更 |
| 换行符不一致 | core.autocrlf + .gitattributes | 统一换行符为 LF |
最佳实践建议
- 团队协作时:在仓库根目录添加
.gitattributes,这样所有成员自动遵循相同规则,无需每个人手动配置 - 服务器部署时:设置
core.filemode false,避免部署脚本修改权限后产生无意义的提交 - IDE 配置:同时配置编辑器使用 LF(VS Code 右下角可以设置,IDEA 也有相关设置)
补充:如果已经有很多历史提交包含这些问题,可以使用
git filter-branch 或 git-filter-repo 重写历史来清理,但这会改变 commit hash,需要团队协调。