Git LFS vs. 标准 Git:大型资产的性能对比

比较 Git LFS 与标准 Git 在处理大型资产时的表现,包括克隆行为、指针文件、LFS 跟踪机制以及何时值得使用 LFS。

Git LFS vs. 标准 Git:大型资产的性能对比

当你的仓库开始包含大型二进制资产时,Git LFS 与标准 Git 的选择就成为一个实际问题。源代码通常能很好地压缩和差异比较,但视频、设计文件、游戏纹理、模型文件和大型数据集会使克隆变慢,历史记录也难以清理。

Git 大文件存储(通常称为 Git LFS)通过将选定的文件替换为小型指针文件,并将实际内容存储在 LFS 对象存储中,来保持普通 Git 仓库的轻量化。这种权衡对许多团队有帮助,但它并非万能。你仍然需要选择合适的文件、提交跟踪规则,并了解 LFS 何时下载内容。

标准 Git 的性能瓶颈

标准 Git 将提交的内容存储在其对象数据库中,并保留足够的历史记录以重建每个提交的版本。这对文本文件非常有效。但当同一个 200 MB 的二进制文件多次更改时,效果就很差。

两个问题会迅速显现:

  • JPEG、MP4、ZIP、PSD 和编译产物等二进制格式通常无法很好地增量压缩。
  • 除非重写历史,否则已删除的文件会保留在历史记录中。
  • 新的克隆会为过去的错误付出代价,因为 Git 历史仍然包含那些旧对象。
  • 仓库维护命令需要检查和处理更多数据。

例如,如果一个团队每个冲刺都提交一个大型导出的设计文件,稍后从当前分支删除该文件并不会移除其旧版本。新的开发者和 CI 工作进程可能仍会下载无人实际使用的数据。

引入 Git 大文件存储 (LFS)

Git LFS 是一个扩展,用于在普通 Git 对象数据库之外管理选定的文件。你的仓库保留一个小的文本指针。实际文件内容存储在由你的 Git 托管平台或其他 LFS 服务器提供的 LFS 存储中。

指针系统

一个 LFS 指针看起来像这样:

version https://git-lfs.github.com/spec/v1
oid sha256:4c2d44962ff3c43734e56598c199589d8995a643...a89c89
size 104857600

普通 Git 看到的就是这个指针。当检出或显式 LFS 命令需要时,Git LFS 客户端会下载实际文件内容。

性能对比:LFS vs. 标准 Git

操作 标准 Git Git LFS
初始克隆 下载包含已提交大型对象的 Git 历史 下载包含指针文件的 Git 历史;LFS 内容可能根据配置在检出时下载
仓库增长 大型二进制文件可能膨胀 .git 历史 Git 历史保持较小,因为跟踪的文件内容是外部的
检出 使用已存在于 Git 数据库中的对象 可能需要为检出的提交获取 LFS 对象
CI 作业 可能浪费下载历史资产的时间 当构建不需要资产时,可以跳过或限制 LFS 下载
清理 需要重写历史以移除旧的已提交 blob 仍需注意,但新的 LFS 跟踪版本不会膨胀普通 Git 历史

重要的细节是检出行为。安装了 Git LFS 后,普通的 git clone 通常会下载检出提交所需的 LFS 文件。如果你只想要指针,可以在克隆时使用 GIT_LFS_SKIP_SMUDGE=1,稍后使用 git lfs pull 获取文件。

何时使用 Git LFS

Git LFS 适用于大型、二进制且预期会更改的文件。常见示例包括:

  • *.psd*.tiff*.blend 以及其他设计或 3D 资产。
  • *.mp4*.mov*.wav 以及其他媒体文件。
  • 项目所需的大型模型文件、测试夹具或数据集。
  • 仅当项目有明确理由进行版本控制时的编译二进制文件。

不要仅仅因为可以就把每个文件都放入 LFS。文本文件、源代码、小型配置文件以及你希望 Git 正常差异比较的文件应保留在标准 Git 中。

在采用 LFS 之前,请检查你的托管服务提供商的存储和带宽限制。GitHub、GitLab、Bitbucket 和自托管平台在配额、计费和保留策略方面可能有所不同。

实施 Git LFS

安装 Git LFS 客户端,然后为你的用户启用其钩子:

git lfs install

跟踪你希望 LFS 管理的模式:

git lfs track "*.psd"
git lfs track "assets/*.mp4"

这些命令会创建或更新 .gitattributes。将该文件与其影响的资产一起提交:

git add .gitattributes assets/
git commit -m "使用 Git LFS 跟踪设计资产"
git push

如果一个大文件已经提交到普通 Git 历史中,使用 LFS 跟踪它只会影响未来的提交。要迁移现有历史,请使用诸如 git lfs migrate import 之类的迁移工具,并仔细协调,因为重写历史会更改提交 ID。

要克隆而不立即下载 LFS 内容,请使用:

GIT_LFS_SKIP_SMUDGE=1 git clone [email protected]:example/assets-heavy-repo.git
cd assets-heavy-repo
git lfs pull --include="assets/*.mp4"

实用要点

对源代码和小型文本文件使用标准 Git。对属于仓库但不应膨胀普通 Git 历史的大型二进制资产使用 Git LFS。

对于团队仓库,尽早添加 LFS 规则,提交 .gitattributes,记录 CI 如何处理 LFS 下载,并验证你的托管平台的 LFS 限制。这样可以在克隆、检出或发布构建时获得性能优势,而不会让开发者感到意外。