Git LFS 即 Git Large File Storage,Git 大文件存储
本文全面介绍Git LFS技术,详细讲解了其工作原理和实现机制。文章解释了Git LFS如何通过指针文件替代实际大文件、使用smudge和clean过滤器处理文件转换以及pre-push钩子实现大文件上传。包含完整的安装配置步骤、常用命令用法、文件追踪设置,以及如何处理新增大文件和导入历史文件的实用场景。
原理

针对音乐、图片、视频、图表、数据库等类型文件等各种 大文件,使用 Git-LFS 技术的本地仓库使用这些文件的 指针文件 代替实际文件,而实际文件存储在远程端,本地仓库会实时追踪这些文件的变动,并更新。
根据 git lfs 官方帮助文档描述:
Git LFS 基于 Git 的 .gitattributs 配置文件的特性,用 smudge 过滤器基于 指针文件 寻找大文件内容, 用 clean 过滤器在对大文件改动时,创建指针文件的新版本。同时还用 pre-push 钩子将大文件上传到 Git LFS 服务器, 即在 git-push 时, 如果提交中包含被 LFS 跟踪的大文件,pre-push 钩子会检测到,并执行上传 Git LFS 服务器的动作。
因此,如果一个仓库中包含 LFS 内容,但是在推送时不想推送这类文件,只要加上 --no-verify 选项就行,即:
1 | $ git push --no-verify |
--no-verify 选项告诉 git push 完全跳过 pre-push 钩子。
前面提到被 LFS 管理的文件,本地仓库中保存的内容实际上是指针文件,其格式类似于下面这样:
1 | $ git show HEAD:2.svg |
version 表示 LFS 的版本
oid 表示文件对象的唯一 hash 值
size 表示文件的大小
安装
安装依赖: Git >= 1.8.5
Linux 系统:
1 | curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash |
其它操作系统上的安装,见官方安装文档:
配置
在 Git 仓库中为仓库设置相关配置:
1 | git lfs install |
此时会在仓库的 .git/config 配置文件中,增加一项新配置:
1 | [lfs] |
选择要用 LFS 追踪的文件:
1 | git lfs track "*.svg" |
git lfs track 会更改仓库中的 .gitattributes 配置文件(如果之前不存在这个文件,则会自动新建):
1 | $ cat .gitattributes |
通过 git lfs lf-files 查看被 LFS 追踪的文件:
1 | $ git lfs ls-files |
如果不想 LFS 追踪某个文件:
1 | $ git lfs untrack "1.png" |
向仓库保存、提交该配置:
1 | git add .gitattributes |
使用场景
在 Git 仓库中,对于非文本文件,如各种多媒体文件,软件制品文件,二进制文件等等,这些文件往往体积比较大,使用 Git 直接管理会导致仓库的体积迅速膨胀,进而导致 Git 的许多操作变慢,同时也影响仓库上传到远程端。
针对这些情况,有人开发出了 git-lfs 工具来特别管理这些大文件。
使用 LFS 管理新增大文件
1 | git add 1.png && git commit -m "add 1.png file" |
提交完成后,提交到远程仓库
1 | $ git push origin master |
使用 LFS 管理历史文件:
如果一个仓库中原来已经提交了一些大文件,此时即使运行 git lfs track 也不会有效的。
为了将仓库中现存的大文件应用到 LFS,需要用 git lfs migrate 导入到 LFS 中:
1 | $ git lfs migrate import --include-ref=master --include="example.svg" |
--include-ref选项指定导入的分支如果向应用到所有分支,则使用
--everything选项
--include选项指定要导入的文件,可以使用通配符,批量导入。
上述操作会改写提交历史,如果不想改写历史,则使用 --no-rewrite 选项,并提供新的 commit 信息:
1 | $ git lfs migrate import --no-rewrite -m "lfs import" |
将本地历史提交中的文件纳入到 LFS 管理后,如果重改了历史,再次推送代码时,需要使用强制推送。
克隆的仓库包含 LFS 管理的文件
如果克隆的仓库中包含 LFS 管理的文件,但最开始获取代码时,没有完全获取 LFS 对象,则文件只会显示为文本指针,此时需要收到获取文件的内容:
1 | $ git lfs pull |
参考链接
https://git-scm.com/docs/gitattributes
https://zzz.buzz/zh/2016/04/19/the-guide-to-git-lfs/
https://docs.github.com/en/github/managing-large-files/about-git-large-file-storage