Git LFS(Git Large File Storage)是 GitHub 官方维护的 Git 扩展,专门用来把仓库里的大文件——比如模型权重、视频、设计稿、数据集——从 Git 对象库挪到外部存储,只在仓库里保留一个轻量的”指针文件”。当你的仓库因为几个几百 MB 的二进制而 clone 动辄几分钟、.git 目录膨胀到几个 G 时,Git LFS 就是最直接的救命方案。本文用一套可照抄的命令,带你从安装、跟踪、迁移到 CI 集成完整落地。
一、为什么需要 Git LFS:普通 Git 的痛点
Git 的设计哲学是”每次提交都保存文件的完整快照”。对于文本代码这没问题,但对大二进制文件(PPT、PSD、训练好的 .pth 模型、游戏素材)来说,每次改动都会把整个文件再存一份进 .git。十几次提交后,历史里就塞满了几十个重复的大对象,任何人 clone 都要把这些历史全拉下来。
Git LFS 的做法是”偷梁换柱”:它给被跟踪的大文件在仓库里放一个几 KB 的指针文件,真实内容存在 LFS 服务器上,下载时通过 smudge 过滤器按需拉取。普通提交者几乎无感,仓库体积却能缩小几个数量级。
| 维度 | 普通 Git | Git LFS |
|---|---|---|
| 大文件存储位置 | 直接进 .git 对象库 | 外部 LFS 存储,仓库仅存指针 |
| clone 体积 | 随历史线性膨胀 | 基本只含当前版本真实文件 |
| 历史拉取 | 全量下载 | 按需(checkout 时拉取) |
| 适用文件 | 文本/源码 | 二进制大文件(>1MB 优先考虑) |
二、安装与初始化
主流平台(GitHub、GitLab、Gitee)都原生支持 LFS。本地安装后,第一次需要在仓库里执行 git lfs install 来注册 Git 的 clean/smudge 过滤器。
# macOS(Homebrew)
brew install git-lfs
# Ubuntu / Debian
sudo apt-get install git-lfs
# 在用户级注册过滤器(只需一次)
git lfs install
# 进入目标仓库后再执行一次,写入 .git/config 的 local 配置
cd your-repo
git lfs install
git lfs install 会在全局或仓库的 Git 配置里写入 filter.lfs 段,告诉 Git 遇到 LFS 指针文件时用 LFS 的驱动去替换内容。装好之后,平时提交和 push 和普通 Git 没有区别。
三、用 .gitattributes 声明要跟踪的大文件
核心就一个命令 git lfs track,它会在仓库根目录生成/追加 .gitattributes 文件。务必把 .gitattributes 一起提交,否则别人 clone 下来不会触发 LFS 过滤。
# 跟踪常见二进制类型
git lfs track "*.psd"
git lfs track "*.png"
git lfs track "*.mp4"
git lfs track "*.zip"
git lfs track "*.bin"
git lfs track "models/*.pth"
# 查看当前跟踪规则
cat .gitattributes
# 把规则本身提交进仓库(关键!)
git add .gitattributes
git commit -m "chore: enable Git LFS for binary assets"
3.1 跟踪规则怎么写才稳
规则按”先具体后宽泛”的顺序匹配。推荐用明确的扩展名或路径,避免一杆子把整个仓库的图片都纳入(README 里的缩略图通常没必要走 LFS)。对于 Monorepo 里某个子包的大资源,可以精确写 packages/ml/assets/*.bin。关于 Monorepo 的依赖与工程化治理,可参考我们之前的前端工程化与 Monorepo 实战。
四、日常提交与拉取工作流
配置完成后,对大文件的操作和 Git 完全一致,LFS 在后台自动接管。几个常用查看命令能帮你确认文件确实走了 LFS。
# 正常提交,LFS 会自动把大文件替换为指针并上传
git add models/bert.pth
git commit -m "feat: add bert model weights"
git push origin main
# 查看哪些文件由 LFS 管理
git lfs ls-files
# 在新机器上拉取时,确保把 LFS 对象也取回来
git lfs pull
git clone https://github.com/you/repo.git # clone 默认即拉取 LFS 对象
指针文件的样子长这样,体积通常只有 130 字节左右:
version https://git-lfs.github.com/spec/v1
oid sha256:4b5b...c3f1
size 512340123
五、迁移已有仓库:把历史里的大文件改成 LFS
如果仓库已经”胖”了,git lfs migrate 能重写历史,把指定类型的历史对象迁到 LFS。注意:重写历史会改变所有提交的 hash,需要团队重新 clone。
# 把历史中所有 *.pth 和 *.mp4 迁到 LFS(改写历史)
git lfs migrate import --include="*.pth,*.mp4" --everything
# 只迁移最近 N 个提交(影响范围更小)
git lfs migrate import --include="*.zip" --recent
# 迁移后强制推送(会改写远端历史,谨慎!)
git push --force --all
5.1 迁移的注意事项
迁移前先通知协作者,迁移后让所有人删除旧 clone 重新拉取,否则本地旧历史仍持有大对象、push 时会把大文件又推回去。建议在 CI 里加一道”禁止大文件直推”的保护(见下文)。
六、存储配额、锁定与跨平台协作
LFS 对象存在外部存储,通常有配额限制。GitHub 免费版默认 1GB 存储 + 1GB 月度带宽,超出需购买。可用以下命令自查占用,并用”文件锁”避免二进制被多人同时改出冲突。
# 列出 LFS 文件及其真实大小
git lfs ls-files --size
# 统计本仓库 LFS 总占用
git lfs ls-files -s | awk '{sum+=$4} END {print sum/1024/1024 " MB"}'
# 锁定一个二进制(如 Unity 场景),防止别人并发修改
git lfs lock assets/scene.unity
git lfs unlock assets/scene.unity
| 平台 | 免费存储配额 | 备注 |
|---|---|---|
| GitHub | 1 GB 存储 / 1 GB 月流量 | 超额按包计费,支持文件锁 |
| GitLab | 随项目存储上限 | 自托管可配对象存储(S3 等) |
| 自建(Gitea + MinIO) | 取决于磁盘 | 适合内网大模型/数据集仓库 |
七、在 CI/CD 里用好 Git LFS
CI 默认 clone 不一定拉取 LFS 对象,训练、构建可能因缺模型权重而失败。显式打开 LFS 拉取是关键。我们的GitHub Actions 实战一文里有完整的流水线范式,这里给出 LFS 相关的关键片段。
# GitHub Actions:确保拉取 LFS 对象
jobs:
train:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
lfs: true # 关键:拉取 LFS 大文件
- name: verify weights
run: git lfs ls-files --size
如果是只提交代码、不希望 CI 拉大文件的场景,可用 GIT_LFS_SKIP_SMUDGE=1 跳过,需要时在脚本里 git lfs pull 具体路径。配合 Docker 做构建缓存时,把 LFS 目录挂进Docker 多阶段构建的缓存层能进一步提速。编辑器侧,VS Code 配合 GitLens 能直观看到 LFS 指针与远程状态。
八、常见误区与排障
| 现象 | 根因 | 解决办法 |
|---|---|---|
| push 后远端文件是文本指针而非真文件 | .gitattributes 未被提交,或 track 在 add 之后才执行 | 先 git lfs track,再 git add 文件;确保 .gitattributes 已提交 |
| clone 下来大文件是 130 字节指针 | 未执行 git lfs pull 或未装 LFS | 安装 LFS 后执行 git lfs pull |
| The remote end hung up unexpectedly | 单文件超平台大小上限或带宽超限 | 拆分文件、升级配额,或改用外部对象存储直传 |
| 历史迁移后同事 push 把大文件推回 | 对方仍用旧 clone | 全员重新 clone;CI 加 pre-receive 钩子拦截 |
九、生产落地检查清单
| ✅ 检查项 | 说明 |
|---|---|
| .gitattributes 已提交 | 团队 clone 才能正确触发 LFS |
| 跟踪规则明确且不过宽 | 避免把 README 缩略图也纳入 |
| CI 显式开启 lfs: true | 防止训练/构建因缺权重失败 |
| 配额与月流量有监控 | 大仓库提前评估超额成本 |
| 二进制并发改用文件锁 | Unity/PSD 等易冲突资源 |
| 历史迁移前通知全员 | 迁移会改写提交 hash |
十、小结
Git LFS 不是银弹,它解决的是”大二进制拖累 Git 性能”这一具体问题。对于动辄上 GB 的模型权重、数据集、设计素材,早用早轻松;对于纯文本代码仓库则完全没必要引入。记住三条铁律:跟踪规则要提交、迁移历史要全员同步、CI 要显式拉取,Git LFS 就能稳稳撑起你的重型仓库。



