Git 大文件存储 (LFS)

管理音频、视频和图形文件等大文件一直是 Git 的缺点之一。一般建议是不要让 Git 仓库大于 1GB 以保持性能。

Git LFS tracking status

Git LFS 跟踪的文件会显示一个图标,以指示文件是存储为 blob 还是 LFS 指针。

如何工作

Git LFS 客户端通过 HTTPS 与 GitLab 服务器通信。它使用 HTTP 基本身份验证来授权客户端请求。请求被授权后,Git LFS 客户端接收指令,从哪里获取或从哪里推送大文件。

要求

已知限制

  • 不支持 Git LFS v1 原始 API,因为它在 LFS 开发早期被弃用。
  • 当 SSH 设置为远程时,Git LFS 对象仍然通过 HTTPS。
  • 任何 Git LFS 请求都要求提供 HTTPS 凭据,因此建议使用良好的 Git 凭据存储。
  • Git LFS 始终假定 HTTPS,因此如果您在 HTTP 上拥有 GitLab 服务器,则必须手动将 URL 添加到 Git 配置
  • 群组 wiki 不支持 Git LFS。

使用 Git LFS

让我们来看看当您需要使用 Git LFS 将大文件检入 Git 仓库时的工作流程。例如,如果您想上传一个非常大的文件并将其检入您的 Git 仓库:

git clone git@gitlab.example.com:group/project.git
git lfs install                       # initialize the Git LFS project
git lfs track "*.iso"                 # select the file extensions that you want to treat as large files

将要跟踪的文件扩展名标记为 LFS 对象后,您可以照常使用 Git,而无需重新执行命令来跟踪具有相同扩展名的文件:

cp ~/tmp/debian.iso ./                # copy a large file into the current directory
git add .                             # add the large file to the project
git commit -am "Added Debian iso"     # commit the file meta data
git push origin main                # sync the git repo and large file to the GitLab server

确保 Git 跟踪了 .gitattributes。否则 Git LFS 对于克隆项目的人无法正常工作:

git add .gitattributes

克隆仓库的工作方式与以前相同。Git 会自动检测 LFS 跟踪的文件并通过 HTTP 克隆它们。如果您使用 SSH URL 执行 git clone 命令,则必须输入您的凭据以进行 HTTP 身份验证。

git clone git@gitlab.example.com:group/project.git

如果您已经克隆了仓库,并且想要获取远端仓库上的最新 LFS 对象,例如来自 origin 的分支:

git lfs fetch origin main

确保您的文件没有在 .gitignore 中列出,否则它们会被 Git 忽略并且不会被推送到远端仓库。

从 LFS 中删除对象

从 LFS 中删除对象:

  1. 使用 git filter-repo 从仓库中删除对象。
  2. 删除您从 .gitattributes 文件中删除的对象的相关 LFS 行并提交这些更改。

项目档案中的 LFS 对象

在 13.5 版本之前,项目源下载将包含 Git LFS 指针而不是实际对象。例如,LFS 指针如下所示:

version https://git-lfs.github.com/spec/v1
oid sha256:3ea5dd307f195f449f0e08234183b82e92c3d5f4cff11c2a6bb014f9e0de12aa
size 177735

在 13.5 及更高版本中,这些指针被转换为上传的 LFS 对象。

故障排查

遇到应该是指针但不是指针的 n 个文件

此错误表明该文件(或多个文件)应由 LFS 跟踪,但由于某种原因,仓库未将它们作为 LFS 进行跟踪。此问题可能是此错误的一个潜在原因:通过 Web 界面上传时文件未使用 LFS 跟踪

要解决此问题,请迁移受影响的文件(或多个文件)并将其推回仓库:

  1. 将文件迁移到 LFS:

    git lfs migrate import --yes --no-rewrite "<your-file>"
    
  2. 推送回您的仓库:

    git push
    

1.(可选)清理您的 .git 文件夹:

   git reflog expire --expire-unreachable=now --all
   git gc --prune=now

error: Repository or object not found

出现此错误的原因有两个:

  • 您无权访问某些 LFS 对象

检查您是否有权推送到项目或从项目中获取。

  • 不允许项目访问 LFS 对象

您尝试推送到项目或从项目中获取的 LFS 对象不再可供项目使用。可能该对象已从服务器中删除。

  • 本地 Git 存储库正在使用已弃用的 LFS API

Invalid status for <url> : 501

Git LFS 将故障记录到日志文件中。 要查看此日志文件,请在项目目录中:

git lfs logs last

如果显示状态 error 501,是因为:

  • 项目设置中未启用 Git LFS。检查您的项目设置并启用 Git LFS。

  • GitLab 服务器上未启用 Git LFS 支持。请与您的管理员核实为什么未在服务器上启用 Git LFS。

  • Git LFS 客户端版本不受 GitLab 服务器支持。使用 git lfs version 检查 Git LFS 版本。使用 git lfs -l 检查项目的 Git 配置以获取废弃 API 的痕迹。如果在配置中设置了 batch = false,请删除该行并尝试更新您的 Git LFS 客户端。仅支持 1.0.1 及更新版本。

getsockopt: connection refused

如果您将 LFS 对象推送到项目并收到这样的错误,则 LFS 客户端正在尝试通过 HTTPS 访问极狐GitLab。但是,您的实例是通过 HTTP 提供的:

Post <URL>/info/lfs/objects/batch: dial tcp IP: getsockopt: connection refused

当 Git 配置中未设置 lfsurl 时,默认情况下 Git LFS 使用 HTTPS 连接会导致这种情况。

为了防止这种情况发生,请在项目 Git 配置中设置 LFS URL:

git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs"

推送对象时始终需要凭据

note8.12 版本为 SSH 添加了 LFS 支持。Git LFS 通信仍然通过 HTTP 进行,但现在 SSH 客户端将正确的凭据传递给 Git LFS 客户端。用户无需执行任何操作。

Git LFS 在每次推送每个对象时使用 HTTP 基本身份验证对用户进行身份验证,因此需要用户 HTTPS 凭据。

默认情况下,Git 支持记住您使用的每个仓库的凭据。Git 凭据手册页中对此进行了描述。

例如,您可以告诉 Git 在您期望推送对象的一段时间内记住密码:

git config --global credential.helper 'cache --timeout=3600'

这会记住一个小时的凭据,之后 Git 操作需要重新进行身份验证。

如果您使用的是 OS X,您可以使用 osxkeychain 来存储和加密您的凭据。 对于 Windows,您可以使用 wincred 或 Microsoft 的 Git Credential Manager for Windows

有关存储用户凭据的各种方法的更多详细信息,请参见 Git 凭据存储文档

推送时缺少 LFS 对象

GitLab 检查文件以检测推送时的 LFS 指针。如果检测到 LFS 指针,会尝试验证这些文件是否已存在于 LFS 中。

验证 LFS 是否安装在本地并考虑使用 git lfs push --all 手动推送。

如果您在极狐GitLab 之外存储 LFS 文件,您可以通过使用项目 API 设置 lfs_enabled: false 来禁用项目上的 LFS。

在外部托管 LFS 对象

通过使用 git config -f .lfsconfig lfs.url https://example.com/<project>.git/info/lfs 设置自定义 LFS URL,可以在外部托管 LFS 对象。

如果您使用像 Nexus 仓库这样的设备来存储 LFS 数据,您可能会选择这样做。如果您选择使用外部 LFS 存储,系统无法验证 LFS 对象。如果您启用了极狐GitLab LFS 支持,则推送将失败。

为了阻止推送失败,可以在项目设置中禁用 LFS 支持,这也会禁用 GitLab LFS 增值(验证 LFS 对象,LFS 的 UI 集成)。