Git LFS 使用注意事项

版本过低导致的报错异常

Git 相关软件版本过低可能导致 Git LFS 功能无法正常使用(例如 batch 接口报错等),特别是 Windows 操作系统下默认安装的版本通常较低。因为新老版本存在兼容性的问题,可能进而引发类似 HTTP 调用异常的情况,导致 LFS 功能无法正常使用。

遇到类似情况,请检查并升级本地 git 和 git-lfs 版本为最新版本后再试, 通常可以顺利解决,下方为相关工具的下载地址:

说明

未安装 git-lfs 导致无法完整拉取文件

如果要拉取包含 Git LFS 文件的代码仓库,则必须在对应环境安装git-lfs,具体可参照文档中的安装章节-如何使用 Git LFS

说明

示例说明:

场景1:用户 A 本地推送若干 Git LFS 文件到远端成功。用户 B 从远端拉取仓库,同时用户 B 环境未安装git-lfs,则拉取后文件内容为 Git LFS Pointer 文件内容(version,oid和size),而无法将真正存储在 Git LFS 的文件拉取到本地。

场景2:用户 A 本地推送若干 Git LFS 文件到远端成功,并且这些文件是 CI/CD 依赖的相关资源。CI/CD在构建或者测试时失败,原因是在 CI/CD 运行的环境中没有安装git-lfs,导致拉取下来的文件为Git LFS Pointer 文件而非真实文件。

如上场景均需要在本机或构建机器上安装git-lfs,安装后使用普通 Git 命令即可正常拉取完整服务端文件。

如何将历史提交中的大文件迁移至 Git LFS

如果Git存储库的提交历史中已有大文件,则git lfs track不会追溯跟踪它们,而只会从新的提交开始应用Git LFS。如果你希望迁移历史提交记录中的大文件到 Git LFS,可以使用git lfs migrate命令进行迁移。

我们来模拟下将历史提交中的 bigfile 后缀的文件,首先将 bigfile 后缀的 pattern 进行 untrack:

$git lfs untrack "*.bigfile"                                                                                                                                                                                  
Untracking "*.bigfile"

随后,添加若干不同大小的多个bigfile 文件,执行git addgit commit后查看提交信息:

$git log -p                                                                                                                                                                                                   
commit 1ca6e34006c6c1206563e8900d17c1503d9b4dce (HEAD -> test, origin/test)                                                                                                                                   
Author: dyroneteng <tenglong***@alibaba-inc.com>                                                                                                                                                              
Date:   Thu Sep 17 14:09:24 2020 +0800                                                                                                                                                                        
                                                                                                                                                                                                              
    old non LFS files                                                                                                                                                                                         
                                                                                                                                                                                                              
diff --git a/.gitattributes b/.gitattributes                                                                                                                                                                  
index c441ad2..e69de29 100644                                                                                                                                                                                 
--- a/.gitattributes                                                                                                                                                                                          
+++ b/.gitattributes
@@ -1 +0,0 @@
-*.bigfile filter=lfs diff=lfs merge=lfs -text
diff --git a/10m.bigfile b/10m.bigfile
new file mode 100644
index 0000000..6c5d403
Binary files /dev/null and b/10m.bigfile differ
diff --git a/11m.bigfile b/11m.bigfile
new file mode 100644
index 0000000..15ae5f2
Binary files /dev/null and b/11m.bigfile differ
diff --git a/12m.bigfile b/12m.bigfile
new file mode 100644
index 0000000..202d95c
Binary files /dev/null and b/12m.bigfile differ
diff --git a/13m.bigfile b/13m.bigfile
new file mode 100644
index 0000000..5b02d1f
Binary files /dev/null and b/13m.bigfile differ
diff --git a/14m.bigfile b/14m.bigfile
new file mode 100644
index 0000000..ad3b355
Binary files /dev/null and b/14m.bigfile differ
diff --git a/15m.bigfile b/15m.bigfile
new file mode 100644
index 0000000..a8510df
Binary files /dev/null and b/15m.bigfile differ

可以看到,在当前的提交1ca6e34006c6c1206563e8900d17c1503d9b4dce中,LFS untrack已经生效,

这是因为 bigfile 的diff内容不是 Pointer 文件内容,而是二进制文件。

随后我们可以执行git lfs migrate info同时指定分支名做为参数,查看该分支 Git LFS 的相关信息:

$git lfs migrate info --include-ref=refs/heads/test
migrate: Sorting commits: ..., done.                                                                                                                                                                          
migrate: Examining commits: 100% (3/3), done.                                                                                                                                                                 
*.bigfile       79 MB   7/7 files(s)    100%
*.gitattributes 46 B    1/2 files(s)     50%

具体迁移的方式,我们可以执行git lfs migrate import,同时指定--include-ref指定分支名以及指定--include指定迁移File Pattern做为参数,进行:

$git lfs migrate import --include-ref=/refs/heads/test --include="*.bigfile"
migrate: Sorting commits: ..., done.                                                                                                                                                                          
migrate: Rewriting commits: 100% (3/3), done.                                                                                                                                                                 
  master        8032589f47a748171e84da94ce6440fe139e99f9 -> 8032589f47a748171e84da94ce6440fe139e99f9
  test          1ca6e34006c6c1206563e8900d17c1503d9b4dce -> 7b1fbac772434d084b4681538602cdf69bf3d8ac            
migrate: Updating refs: ..., done.                                                                                                                                                                            
migrate: checkout: ..., done.

执行上述的迁移命令,从标准输出结果中我们可以看到,master分支的版本没有产生变化,因为我们并未指定迁移master分支,而我们迁移指定的test分支版本已经被更新为7b1fbac772434d084b4681538602cdf69bf3d8ac

$git show 7b1fbac772434d084b4681538602cdf69bf3d8ac
commit 7b1fbac772434d084b4681538602cdf69bf3d8ac (HEAD -> test)
Author: dyroneteng <tenglong***@alibaba-inc.com>
Date:   Thu Sep 17 14:09:24 2020 +0800

    old non LFS files

diff --git a/10m.bigfile b/10m.bigfile
new file mode 100644
index 0000000..f252459
--- /dev/null
+++ b/10m.bigfile
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e5b844cc57f57094ea4585e235f36c78c1cd222262bb89d53c94dcb4d6b3e55d
+size 10485760

### .......
### .......
### .......
### 省略部分输出

在被覆写的提交7b1fbac772434d084b4681538602cdf69bf3d8ac上,我们可以看到和之前的提交1ca6e34006c6c1206563e8900d17c1503d9b4dce发生了变化,前者提交为实际二进制文件差异不显示,而后者已经变为了Git LFS Pointer文件。

最后,如果希望提交在远端生效,需要强制 push 到远端仓库,执行:

$git push --force
重要

  1. 不建议一次性迁移仓库的全部对象变更为Git LFS,可能会存在超时等未知情况,给出的建议为:按照指定分支的方式迁移,参数--include-ref

  2. 强烈建议在迁移Git LFS前在本地备份 Git 仓库,即使迁移异常也可以完整回退到最初仓库状态;

  3. git-lfs-migrate的使用方式参见 git-lfs-migrate迁移工具说明文档

  4. 更多场景的详细迁移指南参见 LFS 迁移指南

相关资料