在 Git 中管理和存储大型文件

Azure DevOps Services |Azure DevOps Server |Azure DevOps Server 2022 |Azure DevOps Server 2020

Git 有助于保持源代码的占用空间较小,因为可以轻松选取版本之间的差异,并且代码很容易压缩。 大型文件在 Git 存储库中存储时出现问题,它们不会很好地压缩,并且版本(如二进制文件)之间完全发生更改。 Git 的快速性能来自于其处理文件的所有版本并从其本地存储切换到文件的所有版本的能力。

如果存储库中有大型、不可区分的文件(例如二进制文件),则每次提交对这些文件进行更改时,都会在存储库中保留这些文件的完整副本。 如果存储库中存在许多版本的这些文件,它们会显著增加签出、分支、提取和克隆代码的时间。

应在 Git 中存储哪些类型的文件?

提交源代码,而不是依赖项

当团队使用编辑器和工具来创建和更新文件时,应将这些文件放入 Git 中,以便团队可以享受 Git 工作流的优势。 不要将其他类型的文件提交到存储库中:例如 DLL、库文件以及团队不创建但代码依赖的其他依赖项。 通过 包管理 将这些文件传递到系统。

包管理将依赖项捆绑在一起,并在部署包时在系统上安装文件。 包经过版本控制,以确保在一个环境中测试的代码在另一个环境中运行相同,前提是环境具有相同的已安装包。

不提交输出

不要从生成和测试提交二进制文件、日志、跟踪输出或诊断数据。 这些输出来自代码,而不是源代码本身。 通过 工作项跟踪 工具或团队文件共享与团队共享日志和跟踪信息。

在 Git 中存储小型、不经常更新的二进制源

不经常更新的二进制源文件提交的版本相对较少。 如果文件大小较小,则它们不会占用太多空间。 Web、图标和其他较小艺术资产的图像可能属于此类别。 最好将这些文件与源的其余部分存储在 Git 中,以便团队可以使用一致的工作流。

重要

即使小型二进制文件经常更新,也可能会导致问题。 例如,对 100 KB 二进制文件的 100 个更改使用 10 个对 1 MB 二进制文件的存储进行多达 10 个更改。 由于更新频率,较小的二进制文件比大型二进制文件更频繁地降低分支性能。

不要提交大量频繁更新的二进制资产

Git 管理文件的一个主要版本,然后在称为 “委派”的过程中仅存储与该版本之间的差异。 通过 Deltification 和文件压缩,Git 可在本地存储库中存储整个代码历史记录。 大型二进制文件通常在版本之间完全更改,并且通常已压缩。 由于版本之间的差异很大,因此 Git 难以管理这些文件。

Git 必须存储每个版本的文件的整个内容,并且难以通过委派和压缩节省空间。 存储这些文件的完整版本会导致存储库大小随时间推移而增加。 增加的存储库大小可降低分支性能,增加克隆时间,并扩展存储要求。

处理大型二进制源文件的策略

  • 不要提交压缩的数据存档。 最好取消压缩文件并提交可变源。 让 Git 处理压缩存储库中的数据。
  • 避免提交已编译的代码和其他二进制依赖项。 提交源并生成依赖项,或使用包管理解决方案对这些文件进行版本控制,并将这些文件提供给系统。
  • 以可变纯文本格式存储配置和其他结构化数据,例如 JSON。

什么是 Git LFS?

如果源文件的版本和频繁更新之间存在较大差异,可以使用 Git 大型文件存储(LFS) 来管理这些文件类型。 Git LFS 是 Git 的扩展,提供数据来描述提交到存储库中的大型文件。 它将二进制文件内容存储在单独的远程存储中。

在存储库中克隆和切换分支时,Git LFS 会从该远程存储下载正确的版本。 本地开发工具以透明方式处理文件,就像直接提交到存储库一样。

优点

Git LFS 的好处是,无论团队创建的文件如何,团队都可以使用熟悉的端到端 Git 工作流。 LFS 处理大型文件,以防止它们对整个存储库产生不利影响。 此外,从版本 2.0 开始,Git LFS 支持 文件锁定 ,以帮助团队处理大型、不可差异的资产,如视频、声音和游戏映射。

Git LFS 在 Azure DevOps Services 中完全受支持和免费。 若要将 LFS 与 Visual Studio 配合使用,需要 Visual Studio 2015 Update 2 或更高版本。 只需按照 说明安装客户端,为本地存储库上的文件设置 LFS 跟踪,然后将更改推送到 Azure Repos。

局限性

在采用 Git LFS 之前,应考虑一些缺点:

  • 团队使用的每个 Git 客户端都必须安装 Git LFS 客户端并了解其 跟踪配置
  • 如果未正确安装并配置 Git LFS 客户端,则克隆存储库时,不会看到通过 Git LFS 提交的二进制文件。 Git 将下载描述大型文件(即 Git LFS 提交到存储库)而不是二进制文件的数据。 提交未安装 Git LFS 客户端的大型二进制文件会将二进制文件推送到存储库。
  • Git 无法合并二进制文件的两个不同版本的更改,即使这两个版本都有一个通用的父文件。 如果两个人同时处理同一文件,则必须协同工作,以协调其更改,以避免覆盖对方的工作。 Git LFS 提供 文件锁定 来帮助。 在开始工作之前,用户仍必须注意始终拉取二进制资产的最新副本。
  • Azure Repos 目前不支持在存储库中使用安全外壳(SSH)和 Git LFS 跟踪的文件。
  • 如果用户通过 Web 界面将二进制文件拖动到为 Git LFS 配置的存储库中,则二进制文件将提交到存储库,而不是通过 Git LFS 客户端提交的指针。
  • 尽管没有严格的文件大小限制,但服务器的可用可用空间和当前工作负荷可能会限制性能和功能。
  • 一个文件上传的时间限制为一小时。

文件格式

写入 Git LFS 跟踪文件的存储库中的文件在每行中都有一些键/值对:

version https://git-lfs.github.com/spec/v1
oid a747cfbbef63fc0a3f5ffca332ae486ee7bf77c1d1b9b2de02e261ef97d085fe
size 4923023

注释

版本值随附的 GitHub URL 仅定义 LFS 指针文件类型。 它不是指向二进制文件的链接。

已知问题

如果将低于 2.4.0 的 LFS 版本与 Azure DevOps Server 配合使用,则需要执行额外的设置步骤 才能通过 NTLM 而不是 Kerberos 进行身份验证。 从 LFS 2.4.0 起,不再需要此步骤,强烈建议升级。