前言

我在接触 WSL 之前,曾在 Windows 下使用 Git Bash 进行 Git 操作。后来在 WSL ( Windows Subsystem for Linux ) 中使用 Git 对这些之前的本地仓库输入git status命令时,惊人的发现所有的文件都被标记成了modified

分析问题

Linux 和 Windows 对于文件的处理最明显差异在权限和换行符。

权限问题

Windows 下的 Git 会忽略对文件权限的处理,它会在提交时默认给予目录755和文件644的权限,而 Linux 下的 Git 会跟踪文件的权限。前面的文章提到过 WSL 通过 DrvFs 访问 Windows 下的文件时文件权限默认为777,所以在 WSL 中访问 Git 仓库时工作区的文件权限同样为777。这就导致了 WSL 中的 Git 认为文件被修改了,故标记为modified

换行符问题

关于换行符,回想起刚学习 Git 时,跟着大佬学习了一个设置:

git config --global core.autocrlf true

它的作用是在提交(commit)时把 Windows 的换行符(CRLF)自动转换为 Linux 的换行符(LF),检出(check out)时把 LF 转换为 CRLF,所以工作区和已提交的换行符即使不同 Windows 下的 Git 也会认为文件是相同的。而 WSL 中的 Git 未经过任何设置,即不转换,那么换行符不同也就是文件不同,故标记为modified

解决方案

解决问题的关键是让 WSL 中的 Git 对文件的理解与 Windows 中的 Git 相同。

权限问题

方案一

core.filemode 是 Git 中对文件权限跟踪的配置项,其在 Windows 中的默认值为false。在 WSL 中输入以下命令可进行设置:

git config --global core.filemode false

方案二

设置 DrvFs 挂载权限,方法参见《DrvFs 文件系统权限问题

换行符问题

方案一(不推荐)

换行符转换设置为true,即提交时转换为LF,检出时转换为CRLF。(原来 Windows 中的设置)

git config --global core.autocrlf true

上面的设置是全局设置,将作用于所有本地仓库,如果只是使用 WSL 中的 Git 来管理 Windows 文件系统中的本地仓库,那这样做没问题。如果还要在 WSL 的文件系统中进行 Git 操作,建议去掉--global,只对相关的仓库进行局部设置。否则在 WSL 中使用 Git 会在克隆和检出时引入 CRLF ,这会导致采用 Git 方式下载安装的程序可能会出现问题,比如 Oh My Zsh 。

方案二

换行符转换设置为input,即提交时把 CRLF 转换成 LF,检出时不转换。

git config --global core.autocrlf input

这样原来 Windows 文件系统中本地仓库的工作区文件即使是 CRLF ,也不会认为文件被修改,而 WSL 中的仓库不会在克隆和检出时引入 CRLF ,灵活性更强。后续可以手动把原来中仓库的换行符统一转换为 LF ,方便管理。

尾巴

在解决这个问题的过程中,发现很多东西并不是别人说什么就是什么,还是需要自己多实践。就比如换行符转换的设置,因为最初不懂,所以看了一些大佬的文章跟着设置成了true,其实在文本编辑器可选换行符的情况下,这样设置是多余的,而且会引发一些问题。

参考资料

git status shows all files as modified

在 Git 中正确设置 CRLF、LF 换行符转换