项目迁移到持久化目录后Git显示所有文件Modified
记录一次项目迁移到持久化目录后,Git将大量文件标记为modified的问题排查过程。
项目迁移到持久化目录后Git显示所有文件Modified的原因和解决方法
最近在 Linux 容器服务器上做实验时,我把项目从非持久化目录:
/home/projects
迁移到了持久化目录:
/data/projects
迁移本身是为了避免容器重启后数据丢失。项目、数据集、实验环境和输出结果都放到 /data 后,理论上会更加安全。
但是迁移完成后,打开 VS Code 时发现了一个奇怪的问题:项目里的几乎所有文件都被标记成了 modified。
一开始看起来像是迁移过程中把所有文件内容都改了,但实际排查后发现,问题并不是文件内容变化,而是 文件权限位变化 导致的 Git 误报。
一、问题现象
迁移完成后,在 VS Code 的 Source Control 面板里,项目中的大量文件都显示为 M。
在命令行中查看 Git 状态:
git status --short
可以看到类似输出:
M README.md
M main.py
M train.py
M configs/default_img.py
M configs/default_vid.py
如果文件很多,几乎整个项目都会显示为已修改状态。
这很容易让人误以为:
是不是迁移过程中把文件内容改坏了?
是不是 rsync 或 mv 出问题了?
是不是 VS Code 自动改了换行符?
是不是 Git 仓库损坏了?
但实际上,大部分情况下并不是文件内容出了问题。
二、先查看具体变化
遇到这种情况,不要急着提交,也不要直接 git restore .。
应该先查看 Git 认为文件到底发生了什么变化。
执行:
git diff --summary
如果看到大量类似输出:
mode change 100644 => 100755 README.md
mode change 100644 => 100755 main.py
mode change 100644 => 100755 train.py
mode change 100644 => 100755 configs/default_img.py
说明 Git 检测到的变化不是文件内容变化,而是文件模式变化。
这里的:
100644
表示普通文件。
而:
100755
表示可执行文件。
也就是说,Git 认为这些文件从普通文件变成了可执行文件。
三、100644 和 100755 是什么
在 Git 中,文件不仅有内容,也有文件模式信息。
常见的文件模式包括:
100644 普通文件,不可执行
100755 普通文件,可执行
120000 符号链接
对于普通 Python、Markdown、配置文件来说,一般应该是:
100644
例如:
README.md
main.py
train.py
default_img.py
正常情况下,它们只是普通文本文件,不一定需要可执行权限。
但是迁移到 /data 后,如果文件系统把这些文件统一显示为可执行权限,Git 就会看到:
100644 => 100755
于是 Git 会认为这些文件被修改了。
四、为什么迁移到 /data 后会这样
这个问题通常和 /data 的挂载方式有关。
在一些云服务器、实验平台或者容器环境中,/data 不是普通的本地磁盘目录,而可能是对象存储、网络存储或者特殊挂载目录。
这类目录对 Linux 文件权限的支持方式,可能和普通磁盘不同。
例如,原本在 /home/projects 中的文件权限是:
-rw-r--r--
迁移到 /data/projects 后,可能变成:
-rwxr-xr-x
也就是多了可执行权限。
从 Linux 角度看,这是权限变化;从 Git 角度看,这就是文件模式变化。
但这并不代表文件内容真的变了。
可以理解为:
文件内容没有变
只是文件权限显示方式变了
Git 默认会跟踪这种权限变化
所以所有文件都显示 modified
五、确认是不是内容变化
可以继续执行:
git diff --numstat
如果看到很多文件对应的是:
0 0 README.md
0 0 main.py
0 0 train.py
这说明这些文件没有新增或删除任何内容。
其中:
第一个 0:新增行数
第二个 0:删除行数
如果都是 0 0,基本可以判断:
文件内容没有变化,只是文件权限模式变化
也可以用普通 diff 查看:
git diff
如果没有看到代码内容的具体改动,而只是看到:
old mode 100644
new mode 100755
那就是典型的 filemode 问题。
六、解决方法:关闭 Git 的 filemode 检查
进入对应的 Git 仓库,执行:
git config core.filemode false
例如:
cd /data/projects/Simple-CCReID
git config core.filemode false
然后再查看状态:
git status --short
这时,大量由于权限变化导致的 M 通常就会消失。
这个命令的作用是告诉 Git:
不要因为文件权限位变化,就把文件标记为 modified
它不会修改代码内容,也不会自动提交任何东西。
七、这个配置改到了哪里
执行:
git config core.filemode false
后,Git 会修改当前仓库的本地配置文件:
.git/config
里面会出现类似内容:
[core]
filemode = false
注意,这是当前仓库的本地配置,不会影响远程仓库,也不会影响其他项目。
所以如果 /data/projects 下有多个 Git 仓库,每个仓库都需要单独设置一次。
八、多个仓库批量处理
如果 /data/projects 下面有多个项目,例如:
/data/projects/Simple-CCReID
/data/projects/DIFFER-main
/data/projects/MSP-ReID-reproduction
可以批量执行:
for repo in /data/projects/*; do
if [ -d "$repo/.git" ]; then
echo "Setting core.filemode=false for $repo"
git -C "$repo" config core.filemode false
fi
done
这个脚本会遍历 /data/projects 下的一级目录,只要发现里面有 .git 目录,就说明它是一个 Git 仓库,然后自动设置:
core.filemode=false
如果你的项目里还有嵌套仓库,需要额外处理更深层级的目录。
九、如果还有文件显示 Modified 怎么办
执行完:
git config core.filemode false
之后,如果还有文件显示 M,那这些文件可能是真的有内容变化。
这时应该继续查看:
git diff
或者查看某个具体文件:
git diff main.py
如果能看到具体代码行发生了变化,那说明它不是权限问题,而是真正的内容改动。
这类文件就需要根据实际情况决定:
保留修改
提交修改
恢复修改
如果确认不要这些内容改动,可以执行:
git restore 文件名
例如:
git restore main.py
不要一上来就执行:
git restore .
因为这会恢复所有未提交修改,可能把你真正需要的代码改动也清掉。
十、完整排查流程
以后如果再遇到“迁移后 Git 全部变 M”的情况,可以按下面流程排查。
第一步,查看状态:
git status --short
第二步,查看是不是权限变化:
git diff --summary
如果看到:
mode change 100644 => 100755
说明是文件权限变化。
第三步,确认内容是否真的变化:
git diff --numstat
如果大多数文件都是:
0 0 文件名
说明内容没有变。
第四步,关闭 filemode 检查:
git config core.filemode false
第五步,再查看状态:
git status --short
如果大量 M 消失,说明问题解决。
十一、是否可以设置成全局配置
也可以设置成全局配置:
git config --global core.filemode false
这样以后当前用户下新使用的 Git 仓库都会默认忽略文件权限位变化。
不过我更推荐先在具体仓库里设置:
git config core.filemode false
原因是有些项目可能确实需要跟踪可执行权限,比如:
shell 脚本
命令行工具
安装脚本
例如:
run.sh
train.sh
install.sh
这些文件是否具有可执行权限,有时候是有意义的。
如果全局关闭 filemode 检查,Git 就不会再提醒这类权限变化。
所以更稳妥的方式是:
哪个仓库因为 /data 挂载导致误报,就在哪个仓库单独设置
十二、总结
把项目从 /home/projects 迁移到 /data/projects 后,如果 Git 显示大量文件 modified,不一定是文件内容被改了。
很多时候只是因为 /data 挂载目录的文件权限表现方式不同,导致 Git 检测到文件模式从:
100644
变成了:
100755
核心判断命令是:
git diff --summary
如果看到大量:
mode change 100644 => 100755
就说明是 filemode 问题。
解决命令是:
git config core.filemode false
设置后,Git 会忽略文件权限位变化,只保留真正的内容改动。
一句话总结:
迁移到 /data 后 Git 全部显示 modified,通常不是文件内容坏了,而是文件权限位变化导致的误报。
这个问题在容器实验环境、云服务器持久化目录、对象存储挂载目录中都比较常见。迁移项目后遇到大量 M,先看 git diff --summary,不要急着提交,也不要直接恢复所有文件。
相关文章
Linux 容器实验环境的数据持久化迁移
记录在 Linux 容器实验环境中,将 /home 下的项目、数据集、环境和输出迁移到持久化目录 /data,并通过软链接保持原路径可用的方法。
PPU显卡环境配置
PPU 显卡服务器深度学习环境配置指南,介绍如何继承系统 PPU 版 PyTorch、创建虚拟环境、安装安全依赖,并处理 torch 不可用和依赖冲突等常见问题。
服务器访问外网:Clash + SSH 反向代理 + 自动重连
本地Windows电脑开启 Clash 代理,然后通过SSH反向隧道,让服务器访问本地Clash代理,从而实现服务器访问外网。
评论
#评论正在加载。如果这里一直没有内容,请检查手机网络是否能访问 GitHub Discussions 和 giscus.app。