Git LFS 实战:用大文件存储拯救臃肿的 Git 仓库

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 过滤器按需拉取。普通提交者几乎无感,仓库体积却能缩小几个数量级。

维度普通 GitGit 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
平台免费存储配额备注
GitHub1 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 就能稳稳撑起你的重型仓库。

上一篇 Embedding 模型选型实战:RAG 与向量检索怎么挑对
下一篇 K8s Pod Pending 排查实战:从调度失败到正常运行
最新评论
Docker 网络模式详解:bridge/host 生产选型 - FSData
Docker 网络模式详解:bridge/host 生产选型 - FSData
8月20日
[…] 注意最后那条:把端口绑定到 127.0.0.1,再由宿主机上的 Nginx 反代进来,比直接 -p 80:80 暴露安全得多,也方便统一做
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
8月20日
[…] Pinia 的工程化用法,可以参考我们之前的实战文章 《Vue3 组合式 API + Pinia:状态管理从入门到实战》,那里覆盖了 Sto
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
8月19日
[…] 状态,点一下就能起停容器,配合我们讲过的 Docker Compose 编排 […]
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
8月19日
[…] 缓存三大坑的本质都是”缓存失效导致请求穿透到数据库”。记住口诀:穿透用布隆、击穿用锁、雪崩用错峰。配合合理的过期策略
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
8月19日
[…] Docker 镜像部署。结合我们之前写的 Docker Compose 一键编排实战,可以在 CI […]