工程实践 2026年6月15日 12 分钟阅读 2821 字

项目迁移到持久化目录后Git显示所有文件Modified

记录一次项目迁移到持久化目录后,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 认为这些文件从普通文件变成了可执行文件。


三、100644100755 是什么

在 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,不要急着提交,也不要直接恢复所有文件。

相关文章

评论

#

评论正在加载。如果这里一直没有内容,请检查手机网络是否能访问 GitHub Discussions 和 giscus.app。