看一个 Git 仓库该不该用 LFS,先别急着改配置,也别只看单个文件有多大。普通 Git 保存大文件的方式是整份快照,每次提交都会把文件内容完整写进 .git 目录。而 LFS 只是把管理方式换掉:仓库里只留一个指向外部存储的指针,真实内容放在远程服务器上。这个区别决定了后面的所有操作。
先看 .git 目录怎么变大
普通 Git 仓库如果包含经常变动的二进制文件,提交几次后 .git 目录会迅速膨胀。一个判断方法是:运行 git count-objects -vH 查看仓库大小,如果 count 和 size 明显超出正常代码仓库,且 pack 文件中主要是大二进制对象,通常意味着有必要引入 LFS。对于大文件,普通 Git 在每次提交时都会保存其全部内容,即使只改动一个字节,也会造成冗余存储;而 LFS 只保存指针,实际内容单独管理。若项目以源码为主,仅偶尔有几个大文件,可以先用普通 Git,等仓库克隆速度显著下降再迁移。
这里说的“明显超出正常代码仓库”没有固定标准。同一个项目里,如果 .git 目录已经比代码目录还大,或者 git count-objects -vH 里的 size-pack 数值在几次提交后翻倍增长,就可以开始认真考虑迁移。但注意,这个判断只适合用在同一类项目上,如果仓库本身存放大量历史资产,就需要结合远程配额一起看。
什么时候该迁移,什么时候再等等
从刚才那段可以看到,迁移的触发点不是文件大小,而是“文件经常变动”和“仓库膨胀速度”。如果项目以源码为主,只有一两个大文件,而且几乎不改,那普通 Git 也够用。真正需要 LFS 的场景,是设计稿、3D 模型、数据集这类文件经常迭代,而且团队多人需要频繁拉取。另一个信号是克隆耗时从几十秒变成几分钟,这时再迁移,历史里的旧对象仍然会卡在仓库里,后面会提到。
切换到 LFS 的操作顺序
使用 Git LFS 时,首先需要安装客户端并运行 git lfs install 启用过滤器。然后要用 git lfs track "*.psd" 之类命令声明要跟踪的扩展名,或者在 .gitattributes 中手动添加规则。关键点是:要在初次提交大文件之前就设置好跟踪规则,否则已提交的文件仍会以普通方式存储;如果文件已经进入历史,需要改写历史或使用迁移工具,风险较高。提交后,通过 git lfs ls-files 可以查看哪些文件被 LFS 管理,确保指针替换生效。
实际操作时,可以按下面这个顺序来:先在项目根目录运行 git lfs install,然后运行 git lfs track "*.psd" 或直接编辑 .gitattributes,加入类似 *.psd filter=lfs diff=lfs merge=lfs -text 的行。接着提交 .gitattributes 和需要纳入 LFS 的初始文件。注意,如果仓库里已经有大文件,必须先确认有没有被 track 命中,再提交;否则那些文件还是会以普通 Git 对象进入历史。
# 启用 LFS
git lfs install
# 声明要跟踪的文件类型
git lfs track "*.psd"
# 查看当前跟踪规则
git lfs track
# 提交配置和文件
git add .gitattributes "*.psd"
git commit -m "启用 LFS 跟踪 PSD 文件"
如果是在已有仓库里临时追加一个后期才想跟踪的大文件,建议先备份,然后评估改写历史的风险。git lfs migrate 可以处理一部分情况,但会改写提交哈希,需要所有协作者同步调整本地分支。
改完后怎么确认 LFS 真的接管了
检查一个仓库是否使用了 LFS,可以查看 .gitattributes 文件中的 filter=lfs 规则;也可以用 git lfs env 查看 LFS 配置。更直接的做法是运行 git lfs ls-files -l,列出被跟踪的文件和提交对象。若想确认某个具体文件是否是指针,可以用 git cat-file blob HEAD:path/to/file 查看内容,如果出现“version https://git-lfs.github.com/spec/v1”的字符串,则说明该文件由 LFS 管理。普通 Git 模式下,该命令会直接输出文件的实际内容,两者差异一目了然。
这个检查习惯建议保留到协作正常之后。有时候克隆一个 LFS 仓库,某些文件看起来是正常的,但打开其实是指针,往往是因为客户端钩子没生效或服务器没有正确返回对象。运行 git lfs install 会安装需要的过滤器,再执行 git lfs pull 就能把缺失内容拉回来。
使用 LFS 的边界和注意点
LFS 需要单独的服务器支持,GitHub、GitLab 都提供配额,但配额超了推送会被拒绝。而且 LFS 的下载请求和存储体积都会计费,如果团队频繁拉取一个巨大的文件,配额用完后别人的推送也会受影响。所以在启用前,先确认远程仓库所在平台的 LFS 额度,这个值不是固定的,得结合具体账号和套餐来看。
另一个边界是:LFS 只对“后续新提交的内容”做优化,历史里已经存在的大文件对象不会因为启用 LFS 就自动清除。仓库克隆时,普通 Git 对象仍然会被完整下载,只有重写历史清理旧对象,才能让克隆体积真正降下来。这就意味着,迁移前仓库越庞大,迁移的工程量越大,不是简单 install 就能解决。
最后,不要把 LFS 当成万能解。如果某个文件本身经常变动且体积巨大,比如上百 MB 的二进制文件,即使走 LFS,每次修改后成员拉取时仍要下载一份完整内容。更合适的做法是把这类文件放在对象存储或外部服务里,仓库里只保留下载脚本或访问信息。