Git LFS 大文件优化说明

Git LFS 大文件优化说明

本文档用于说明本项目如何使用 Git LFS 管理 MP3 等大文件,并给出常见场景下的操作流程、验证方法和风险提醒。

当前项目是 MP3 音频库,mp3/ 目录下的音频文件不适合直接作为普通 Git 对象长期提交。仓库已配置:

gitattributes 复制代码
*.mp3 filter=lfs diff=lfs merge=lfs -text

这表示所有 .mp3 文件都会由 Git LFS 管理。

1. 为什么需要 Git LFS

Git 适合管理源码、配置文件、Markdown 文档等文本类文件,不适合直接管理大量二进制大文件,例如:

  • MP3 音频
  • 视频
  • 图片资源
  • 模型文件
  • 压缩包

如果直接把大文件提交到普通 Git 历史中,会产生几个问题:

  • Git 会保存完整二进制内容
  • 文件每次修改都会产生新的对象
  • 仓库历史会快速膨胀
  • clonepullpush 速度下降
  • GitHub 单次接收的 pack 文件有大小限制

可以用下面的命令检查仓库对象大小:

bash 复制代码
git count-objects -vH

如果出现类似结果:

text 复制代码
size-pack: 2.36 GiB

推送时可能遇到:

text 复制代码
remote: fatal: pack exceeds maximum allowed size (2.00 GiB)
error: remote unpack failed: index-pack failed

原因是 GitHub 单次接收的 pack 文件超过 2GB 限制。

2. Git LFS 是什么

Git LFS(Large File Storage)是 Git 官方提供的大文件存储扩展。

核心思想:

Git 仓库中保存大文件指针,真正的大文件存储在 Git LFS 服务端。

普通 Git 保存大文件时:

text 复制代码
Git Repository

.git/objects

├── source.js
└── xxx.mp3 (100MB)

使用 Git LFS 后:

text 复制代码
Git Repository

.git/objects

├── source.js
└── xxx.mp3 pointer

Git LFS Storage

└── xxx.mp3 (100MB)

Git 中实际保存的是类似这样的指针文件:

text 复制代码
version https://git-lfs.github.com/spec/v1
oid sha256:xxxxxx
size 104857600

真正的 MP3 文件存储在 LFS 服务端。

3. 安装 Git LFS

macOS:

bash 复制代码
brew install git-lfs
git lfs install
git lfs version

Ubuntu / Debian:

bash 复制代码
sudo apt update
sudo apt install git-lfs
git lfs install
git lfs version

git lfs install 会安装本机 Git LFS hooks。每台开发机器通常只需要执行一次。

4. 本项目的大文件配置

本项目根目录的 .gitattributes 已包含:

gitattributes 复制代码
*.mp3 filter=lfs diff=lfs merge=lfs -text

这会让所有 .mp3 文件进入 Git LFS。

如果在新仓库中首次配置,可以执行:

bash 复制代码
git lfs track "*.mp3"
git add .gitattributes

生成或更新的 .gitattributes 内容应类似:

gitattributes 复制代码
*.mp3 filter=lfs diff=lfs merge=lfs -text

建议同时提交 .gitattributes,否则其他人 clone 仓库后无法自动得到相同的 LFS 规则。

5. 验证 Git LFS 配置

查看规则:

bash 复制代码
cat .gitattributes

检查某个 MP3 文件是否命中 LFS 规则:

bash 复制代码
git check-attr filter -- mp3/test.mp3

正确结果:

text 复制代码
mp3/test.mp3: filter: lfs

错误结果:

text 复制代码
mp3/test.mp3: filter: unspecified

如果显示 unspecified,表示该文件没有进入 LFS 规则,需要检查 .gitattributes 是否存在、路径是否正确、文件扩展名是否匹配。

查看已经由 LFS 跟踪的文件:

bash 复制代码
git lfs ls-files

查看当前 LFS 状态:

bash 复制代码
git lfs status

6. 新项目使用 Git LFS 的推荐流程

新项目建议先配置 LFS,再添加 MP3 文件:

bash 复制代码
git init
git lfs install
git lfs track "*.mp3"

git add .gitattributes
git add .
git commit -m "initial commit with git-lfs"

git remote add origin git@github.com:xxx/repo.git
git push -u origin main

重点是:先 git lfs track "*.mp3",再 git add 大文件。

如果先把 MP3 加入普通 Git,再配置 LFS,旧历史里仍然会保留普通 Git 对象。

7. 已提交大文件迁移到 Git LFS

如果 MP3 已经提交到普通 Git 历史中,例如:

text 复制代码
commit 1:
  add genesis.mp3

commit 2:
  modify genesis.mp3

可以用 Git LFS 迁移历史:

bash 复制代码
git lfs migrate import \
  --include="*.mp3" \
  --everything

迁移后检查:

bash 复制代码
git lfs ls-files
git count-objects -vH

然后推送:

bash 复制代码
git push origin main --force

注意:git lfs migrate import --everything 会重写 Git 历史,--force 推送会覆盖远端分支历史。执行前必须确认:

  • 所有人都已停止向旧分支提交
  • 已备份重要分支或 tag
  • 团队成员知道需要重新 clone 或重置本地分支
  • GitHub Actions、部署环境、镜像仓库都能接受历史重写

如果仓库已经公开发布或多人协作,优先选择新建迁移分支、测试通过后再统一切换。

8. 未发布项目删除 Git 历史重新初始化

如果项目尚未发布、没有其他人基于当前 Git 历史协作,可以选择删除 Git 历史后重新初始化。

危险操作,执行前请确认当前目录正确,并做好备份:

bash 复制代码
rm -rf .git

重新初始化:

bash 复制代码
git init
git branch -M main
git lfs install
git lfs track "*.mp3"

提交:

bash 复制代码
git add .
git commit -m "initial commit with git-lfs"

推送:

bash 复制代码
git remote add origin git@github.com:xxx/repo.git
git push -u origin main --force

优点:

  • 清除旧历史
  • 仓库大小立即下降
  • 操作简单

限制:

  • 会丢失旧提交历史
  • 不适合已经发布或多人协作的仓库
  • 需要重新设置远端和分支保护策略

9. Clone 后是否能获得完整 MP3

可以,前提是本机安装并启用了 Git LFS。

正常 clone:

bash 复制代码
git clone git@github.com:xxx/repo.git

Git LFS 会自动下载真实文件,目录中看到的是完整 MP3:

text 复制代码
project/

├── src/
├── README.md
└── mp3/
    ├── genesis.mp3
    └── matthew.mp3

如果没有安装 Git LFS,可能看到的是指针文件:

text 复制代码
version https://git-lfs.github.com/spec/v1
oid sha256:xxxx
size xxxx

这不是音频文件本体。安装并拉取 LFS 内容:

bash 复制代码
git lfs install
git lfs pull

10. CI/CD 中使用 Git LFS

GitHub Actions 使用 actions/checkout 时,需要开启 LFS:

yaml 复制代码
- uses: actions/checkout@v4
  with:
    lfs: true

否则 CI 拉取到的可能只是 LFS pointer,而不是完整 MP3 文件。

如果 CI 中只需要代码、不需要音频,可以不拉取 LFS,以减少构建时间和流量。

11. 常用排查命令

检查仓库对象大小:

bash 复制代码
git count-objects -vH

查看 LFS 跟踪规则:

bash 复制代码
git lfs track
cat .gitattributes

检查文件属性:

bash 复制代码
git check-attr filter -- mp3/test.mp3

列出 LFS 文件:

bash 复制代码
git lfs ls-files

下载 LFS 文件:

bash 复制代码
git lfs pull

检查 LFS 环境:

bash 复制代码
git lfs env

12. 本项目推荐示例

针对当前 xxx-mp3-cn 仓库,推荐把普通文件和 MP3 文件分开提交。一次性把所有文件放进同一个 commit,容易在 LFS 规则未生效、缓存未清理或误 add 的情况下,把 MP3 作为普通 Git 对象写进历史。

推荐流程如下。

先初始化 Git LFS 并配置 MP3 跟踪规则:

bash 复制代码
git lfs install
git lfs track "*.mp3"
git add .gitattributes

先提交非 MP3 文件,例如源码、脚本、文档、转写文本等:

bash 复制代码
git add README.md scripts books .transcripts
git commit -m "add project files"

查看此时 Git pack 大小:

bash 复制代码
git count-objects -vH

这一步的 pack 应该比较小,因为还没有提交 MP3 本体。

然后再单独添加 MP3 文件:

bash 复制代码
git add mp3
git status --short
git lfs ls-files

确认 git lfs ls-files 能看到 MP3 文件后,再提交音频:

bash 复制代码
git commit -m "add mp3 files with git-lfs"

再次查看 Git pack 大小:

bash 复制代码
git count-objects -vH

如果 LFS 生效,Git pack 不应该因为 MP3 文件大幅膨胀;MP3 的真实内容会进入 LFS 存储,Git 历史中只保存 pointer。

最后推送:

bash 复制代码
git push -u origin main

这个"两次 commit"的方式更容易排查问题:

  • 第一次 commit 只验证普通项目文件是否正常
  • 第二次 commit 专门验证 MP3 是否进入 Git LFS
  • 如果 pack 在添加 MP3 后突然变大,说明 LFS 可能没有生效,应先停止推送并检查 .gitattributesgit lfs ls-filesgit check-attr
  • 避免一次 commit 把普通文件和大文件混在一起,导致问题发生后很难判断是哪一步引入了大对象

CI 如需读取真实音频,actions/checkout 仍需配置:

yaml 复制代码
- uses: actions/checkout@v4
  with:
    lfs: true
相关推荐
晴雨天️2 天前
Git工具使用指南
笔记·git
酷可达拉斯2 天前
Linux操作系统-简单内核优化
linux·git·php
触底反弹2 天前
🔥 Git 从零到精通:彻底搞懂核心概念与工作原理
git·面试·开源
tokenKe3 天前
Epic Games 发布下一代版本控制系统 Lore:被 HN 干到 1000+ 分的“游戏版 Git“
git·游戏
Eira-Z3 天前
git(持续学习中...)
git·学习
leoZ2313 天前
Git 集成实战完全指南(五):Git Blame 与历史追踪
大数据·git·elasticsearch
leoZ2313 天前
Git 集成实战完全指南(六):Git 标签与版本管理
大数据·git·elasticsearch
leoZ2314 天前
Git 集成实战完全指南(三):自动化 Commit 与 PR
大数据·git·elasticsearch
国服第二切图仔4 天前
002-Claude Code 项目解读:入口与启动流程
linux·git·ubuntu