git lfs pointer 报错解决
1. 问题说明
在git管理中,有时候会遇到下面的报错:
1 | Encountered 1 file that should have been a pointer, but wasn't: |
或像下面这样:
1 | Encountered <n> files that should have been pointers, but weren't: |
调查一番后发现,这种报错的核心原因是本应该用Git LFS管理的文件,直接被git来管理了。报错中提到的pointer ,实际上指的就是Git LFS 格式的文件,它不包含完整的数据,而只是一个指向完整数据的指针。
知道这个原因后,解决方法也很简单,而且git lfs v2.2.1 及以后版本提供了git lfs migrate 命令,专门来处理这种情况,也就是将Git管理的文件迁移到用Git LFS来管理,例如,如果已经有一个可以track *.mp4 二进制文件的.gitattributes 配置,使用下面的命令可以将所有mp4文件转换为用Git LFS来管理:
1 | git lfs migrate import --include="*.mp4" |
执行完这个命令后,还需要用下面的命令清理.git 目录,将缓存的object数据去掉:
1 | git reflog expire --expire-unreachable=now --all |
2. 为什么会出现这种错误
我自己的经验中,最常出现这种情况的原因是,Xcode中添加文件到工程,Xcode自动添加文件到Git管理中,但没有遵循.gitattributes 文件中的规则,将本来应该用Git LFS管理的文件格式直接提交到Git了,所以出现冲突。
另外一种情况是git lfs 配置项被临时禁用,导致添加某些文件的过程中lfs 机制没有生效,下面是这种情况的一个完整复现例子,实际中出现的可能性不大:
1 |
|
这个脚本中,git config --local filter.lfs.process 和git config --local filter.lfs.required false 就是关掉LFS作用的两条命令。
3. git lfs 的调试命令
在调查问题的过程中,也发现了更多的git lfs的命令,这里也列出来,调试问题的时候时有用的。
git lfs status 会列出当前lfs文件的修改,包括已经git commit提交的,已经git add stage但没git commit提交的,和没有git add处于unstaged的所有lfs 文件。
git lfs pull 会拉取原始的文件,这条命令可以重新拉取git clone时没有拉取的文件。
git lfs ls-files 会列出所有用git LFS 管理的文件,调试很有用。
git lfs fsck 命令会检查用Git LFS管理的文件是否正常,像上面遇到的问题,用这个命令就能很容易测试出来。--objects 选项只检查对应的object对象,而--pointers 只检查对应的pointer文件。
4. 参考资料
除了上面提供的解决方案外,还有一些解决方法,但可能会需要--hard 提交,有危险性,这里就不列出来了 ,具体可以在下面的参考资料中找到。