今天遇到一个乍看之下匪夷所思的问题:使用 git clone
后,未对 clone 下来的仓库做任何操作,但是 git status
却显示有文件被修改了!感觉超级诡异…
经过一番定位,发现项目使用了 Git LFS
,而那些显示为「已修改」的文件,正是被 lfs 追踪的文件。
问题复现
在命令行中运行下面的命令,创建一个测试项目:
|
上面的命令先向仓库中 commit 了一个二进制文件,然后没有用 git lfs track
命令添加要跟踪的文件类型,而是使用 echo *.bin filter=lfs diff=lfs merge=lfs -text > .gitattributes
创建了 .gitattributes
文件。
最后的 git status 会显示当前的工作空间是 clean 的:
|
把这个测试工程推送到 Github 上,重新 clone 到本地,然后再执行 git status
,这时会发现项目当中的 lfs.bin 文件显示被修改了:
|
所以问题的原因就是这些文件在被加入到 .gitattributes 文件中前就已经 commit 到了库里面。然后又手工修改了 .gitattributes 文件,导致使用 git status 不会显示有文件修改,然后就 push 到库上了,别人再 clone 的时候就会显示这些文件被修改了。
结论
- 如果你的库中已经发生了上述的情况,将 git status 显示的修改文件 commit 一次,git lfs 就会将这些文件追踪起来。
- 不要手动修改 .gitattributes 文件,总是使用 git lfs track 命令来添加要追踪的文件类型(原因见下一节)。
扩展
在上面的结论当中提到,「总是用 git lfs track
命令来添加要追踪的文件类型」,原因是 git-lfs 对 track 命令做了优化(1.2.0及之后的版本链接),track的同时会去修改被 track 文件的 mtime/atime
,然后 git status 就会认为这个文件被修改了,下面的几行命令和问题复现中的唯一区别就是使用了 git lfs track
来添加追踪类型:
|
想要了解具体细节的话可以参考以下两个 Github 的 Issue: