跳到主要内容

Git LFS 大文件存储

Git Large File Storage (LFS) 是 Git 的一个扩展,专门用于处理大文件。Git 本身不适合管理大型二进制文件,因为每次修改都会生成完整的副本,导致仓库体积迅速膨胀。Git LFS 通过将大文件存储在远程服务器上,而在 Git 仓库中只保留指向这些文件的轻量级引用,解决了这个问题。

为什么需要 Git LFS?

Git 存储大文件的问题

Git 的设计初衷是管理文本文件(源代码),对于二进制大文件存在以下问题:

  1. 仓库体积膨胀:每次修改二进制文件,Git 都会存储完整的副本,而不是差异
  2. 克隆变慢:大文件会让克隆和拉取变得非常缓慢
  3. 网络带宽浪费:即使只修改了一小部分,也要传输整个文件
  4. 磁盘空间占用大:历史版本都会保留完整副本

Git LFS 的解决方案

Git LFS 的工作原理:

  1. 在提交时,将大文件替换为一个轻量级的指针文件
  2. 大文件的实际内容存储在 LFS 服务器上
  3. 在检出时,LFS 自动下载指针指向的实际文件内容

安装 Git LFS

Windows

# 使用 winget
winget install Git.Git.LFS

# 或下载安装包
# https://git-lfs.github.com/

macOS

# 使用 Homebrew
brew install git-lfs

# 使用 MacPorts
port install git-lfs

Linux

# Debian/Ubuntu
sudo apt update
sudo apt install git-lfs

# CentOS/RHEL
sudo yum install git-lfs

# Fedora
sudo dnf install git-lfs

# Arch Linux
sudo pacman -S git-lfs

初始化

安装后,需要为当前用户初始化 Git LFS:

git lfs install

# 输出
Git LFS initialized.

这个命令会在你的全局 Git 配置中添加必要的设置,只需运行一次。

基本使用

1. 追踪大文件

告诉 Git LFS 哪些文件需要使用 LFS 管理:

# 追踪特定扩展名的文件
git lfs track "*.psd"

# 追踪特定文件
git lfs track "assets/video.mp4"

# 追踪某个目录下的所有文件
git lfs track "assets/**"

# 追踪所有大于 100KB 的文件
git lfs track --filename="*.bin" --above=100KB

2. 查看 LFS 追踪规则

# 查看当前追踪规则
git lfs track

# 输出示例
Listing tracked patterns
*.psd (.gitattributes)
*.mp4 (.gitattributes)
assets/** (.gitattributes)

3. 提交追踪规则

git lfs track 命令会在项目根目录创建或更新 .gitattributes 文件,这个文件需要提交到仓库:

# 查看 .gitattributes 内容
cat .gitattributes

# 输出示例
*.psd filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
assets/** filter=lfs diff=lfs merge=lfs -text
# 提交 .gitattributes
git add .gitattributes
git commit -m "配置 Git LFS 追踪规则"

4. 正常提交大文件

配置好后,正常使用 Git 命令即可,LFS 会自动处理:

# 添加大文件
git add design.psd

# 提交
git commit -m "添加设计稿"

# 推送
git push origin main

5. 查看文件状态

# 查看 LFS 文件状态
git lfs ls-files

# 输出示例
d4e5f6g7 - design.psd
a1b2c3d4 - video.mp4

工作原理详解

指针文件

Git LFS 用指针文件替换大文件,指针文件是一个文本文件,包含实际文件的引用信息:

version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345678
  • version:LFS 规范版本
  • oid:对象 ID,通常是文件内容的 SHA-256 哈希
  • size:文件大小(字节)

工作流程

Clean/Smudge 过滤器

Git LFS 使用 Git 的 clean/smudge 过滤器机制:

  • Clean 过滤器:在 git add 时触发,将大文件转换为指针
  • Smudge 过滤器:在 git checkout 时触发,将指针还原为大文件

这由 .gitattributes 中的配置驱动:

*.psd filter=lfs diff=lfs merge=lfs -text
  • filter=lfs:使用 LFS 过滤器
  • diff=lfs:使用 LFS 进行差异比较
  • merge=lfs:使用 LFS 进行合并
  • -text:标记为二进制文件

常用命令

文件管理

# 追踪文件
git lfs track "*.extension"

# 取消追踪
git lfs untrack "*.extension"

# 查看已追踪的文件
git lfs track

# 列出当前 LFS 管理的文件
git lfs ls-files

# 查看文件信息
git lfs pointer --file=large-file.bin

数据传输

# 推送 LFS 对象到服务器
git lfs push --all origin

# 推送特定分支的 LFS 对象
git lfs push origin main

# 从服务器拉取 LFS 对象
git lfs pull

# 获取 LFS 对象信息但不下载
git lfs fetch

# 检出 LFS 文件
git lfs checkout

数据迁移

# 将历史提交中的大文件迁移到 LFS
git lfs migrate import --include="*.psd" --everything

# 只迁移特定分支
git lfs migrate import --include="*.psd" --include-ref=refs/heads/main

# 导出 LFS 文件到普通 Git 对象
git lfs migrate export --include="*.psd" --everything

信息查看

# 查看 LFS 配置
git lfs env

# 查看 LFS 对象信息
git lfs objects

# 查看 LFS 日志
git lfs logs

# 查看 LFS 存储使用情况
git lfs du

迁移现有仓库到 LFS

如果你已经有一个包含大文件的仓库,可以将历史大文件迁移到 LFS。

方法一:使用 git lfs migrate

这是推荐的方法,会重写 Git 历史:

# 迁移所有历史中的 .psd 文件
git lfs migrate import --include="*.psd" --everything

# 迁移多种文件类型
git lfs migrate import --include="*.psd,*.mp4,*.zip" --everything

# 只迁移 main 分支
git lfs migrate import --include="*.psd" --include-ref=refs/heads/main

# 迁移最近的 N 次提交
git lfs migrate import --include="*.psd" --above=1MB HEAD~10..HEAD

迁移完成后,需要强制推送:

# 强制推送(会重写历史)
git push --force --all
git push --force --tags

警告:迁移会重写 Git 历史,所有协作者需要重新克隆仓库。

方法二:手动迁移

对于不想重写历史的情况,可以只对新提交使用 LFS:

# 1. 配置 LFS 追踪
git lfs track "*.psd"
git add .gitattributes
git commit -m "配置 LFS"

# 2. 从 Git 中移除大文件
git rm --cached large-file.psd

# 3. 重新添加(这次会使用 LFS)
git add large-file.psd
git commit -m "迁移大文件到 LFS"
git push

这种方法不会减少历史仓库的体积,但之后的大文件会用 LFS 管理。

托管服务支持

GitHub

GitHub 对 LFS 提供良好支持:

  • 免费账户:1 GB 存储空间,每月 1 GB 带宽
  • 付费计划:可购买额外存储和带宽
# 查看当前仓库的 LFS 使用情况
gh api repos/{owner}/{repo}/content-references

GitLab

GitLab 也支持 LFS:

  • 自托管:无限制
  • GitLab.com:免费账户有配额限制

配置 .lfsconfig

[lfs]
url = https://gitlab.example.com/group/project.git/info/lfs

自建 LFS 服务器

可以使用开源的 LFS 服务器实现:

配置自定义 LFS 服务器:

# 为仓库配置 LFS URL
git config lfs.url https://lfs.example.com/owner/repo

# 或在 .lfsconfig 中配置
[lfs]
url = https://lfs.example.com/owner/repo

最佳实践

1. 选择合适的文件类型

Git LFS 适合以下类型的文件:

  • 设计文件:.psd.ai.sketch
  • 视频文件:.mp4.mov.avi
  • 音频文件:.mp3.wav.flac
  • 3D 模型:.obj.fbx.blend
  • 数据集:.csv(大型)、.parquet
  • 压缩包:.zip.tar.gz
  • 二进制文件:.exe.dll.so

2. 合理设置追踪规则

# 推荐:按扩展名追踪
git lfs track "*.psd"

# 不推荐:追踪所有大文件(可能误伤代码文件)
# git lfs track --above=100KB

3. 提交 .gitattributes

确保 .gitattributes 文件被提交到仓库,这样所有协作者都能使用相同的 LFS 配置:

git add .gitattributes
git commit -m "添加 LFS 配置"

4. 团队协作注意事项

  • 所有团队成员都需要安装 Git LFS
  • 迁移历史时通知所有协作者重新克隆
  • 定期检查 LFS 存储使用情况

5. 锁定大文件(可选)

对于不适合合并的二进制文件,可以使用锁定功能:

# 锁定文件
git lfs lock design.psd

# 查看锁定的文件
git lfs locks

# 解锁文件
git lfs unlock design.psd

常见问题解决

问题:推送时 LFS 文件没有上传

# 手动推送 LFS 对象
git lfs push --all origin

# 或重新安装 LFS 钩子
git lfs install --force

问题:克隆后 LFS 文件没有下载

# 手动拉取 LFS 文件
git lfs pull

# 检查 LFS 配置
git lfs env

问题:迁移后仓库体积没有减小

# 清理旧的 reflog 和垃圾对象
git reflog expire --expire=now --all
git gc --prune=now --aggressive

# 检查仓库大小
git count-objects -vH

问题:LFS 配额不足

# 查看当前使用情况
git lfs du

# 删除不需要的历史 LFS 对象(需要迁移重写历史)
git lfs migrate import --include="*.psd" --above=10MB --everything

.gitattributes 示例

# 设计文件
*.psd filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.sketch filter=lfs diff=lfs merge=lfs -text

# 视频文件
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.mov filter=lfs diff=lfs merge=lfs -text

# 音频文件
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text

# 压缩包
*.zip filter=lfs diff=lfs merge=lfs -text
*.tar.gz filter=lfs diff=lfs merge=lfs -text

# 二进制文件
*.exe filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.so filter=lfs diff=lfs merge=lfs -text

# 数据文件
*.parquet filter=lfs diff=lfs merge=lfs -text

小结

本章我们学习了:

  1. Git LFS 的作用:解决 Git 管理大文件的问题
  2. 安装和配置:在不同平台安装 Git LFS
  3. 基本使用:追踪文件、提交、推送
  4. 工作原理:指针文件、clean/smudge 过滤器
  5. 迁移现有仓库:使用 git lfs migrate
  6. 托管服务支持:GitHub、GitLab、自建服务器
  7. 最佳实践:选择文件类型、团队协作

参考资料