为什么以及如何使用Git LFS

大型二进制文件对于每个版本控制系统来说都是一个难题:对大型二进制文件的任何微小更改都会再次将完整(大型)文件添加到存储库中。这会很快导致巨大的存储库大小。Git的LFS (Large File Storage)恰好解决了这个问题。

 Git LFS是什么?

Git LFS 是一个开源项目,是对Git的扩展。目标是更有效地处理大型文件和二进制文件到存储库中。

  • 大型文件每次更新都会增加您存储库的历史记录;
  • 大文件将使读取和拉取速度变慢;
  • Git将二进制文件的更新视为完整的文件更改,而不是例如仅存储与文件差异的纯文本文件。如果您经常更改二进制文件,那么您的Git存储库将增加大小。一定时间后,由于存储库大小的增加,Git命令将变慢。

因此,当您的存储库中有大文件和/或很多二进制文件时,建议使用Git LFS。当文件或文件类型标记为LFS文件时,Git LFS使用指针而不是实际文件。当Git LFS文件被拉到本地存储库时,该文件将通过过滤器发送,该过滤器会将指针替换为实际文件。实际文件位于远程服务器上,提取的实际文件位于本地存储库中的缓存中。这意味着本地存储库的大小将受到限制,但是远程存储库当然将包含所有实际文件和差异。

安装

安装将在Ubuntu上完成,我们假定已经安装了Git。如前所述,Git LFS是Git的扩展,因此需要单独安装:

$ sudo apt安装git-lfs

首先创建一个空的新Git存储库:

$ mkdir mygitlfsplanet
$ cd mygitlfsplanet
$ git init
在 /home/user/mygitlfsplanet/.git/中初始化了空的Git存储库

切换到您的Git存储库(.git 目录所在的 位置)并执行以下命令以激活Git LFS:

$ git lfs install
Updated git hooks.
Git LFS initialized.

首先,查看主目录中的.gitconfig文件。添加了以下部分:

[filter "lfs"]
    clean = git-lfs clean -- %f
    smudge = git-lfs smudge -- %f
    process = git-lfs filter-process
    required = true

切换到目录mygitlfsplanet / .git / hooks。已添加/更新了以下挂钩,并包含git-lfs命令,这些命令将在触发挂钩时执行:

  • post-checkout
  • post-commit
  • post-merge
  • pre-push

还添加了一个目录mygitlfsplanet / .git / lfs,这是我们一直在谈论的本地缓存。

配置

现在,我们已经为存储库安装了Git LFS,是时候配置我们要与Git LFS关联的文件类型了。此信息将添加到存储库中的.gitattributes文件中。建议提交此文件并将其推送到您的存储库,以使每个开发人员都使用相同的Git LFS配置。将文件类型与Git LFS关联的最简单方法是使用git lfs track命令。让我们将所有jpg文件关联到Git LFS:

$ git lfs track "*.jpg"
Tracking "*.jpg"

.gitattributes文件已创建并包含以下信息:

*.jpg filter=lfs diff=lfs merge=lfs -text

如果我们的存储库中有一个包含大型xml文件的大文件目录,并且我们不想将所有xml文件与Git LFS关联,而只希望将特定目录中的文件关联到Git LFS,该怎么办?我们可以跟踪目录大文件,并且仅将该目录中的xml文件与Git LFS相关联:

$ git lfs track "largefiles/*.xml"
Tracking "largefiles/*.xml"

剩下要做的就是将.gitattributes文件提交到我们的本地存储库中。

 Git LFS实战

现在我们已经准备好所有准备工作,现在该采取行动了。我们将在存储库的根目录中添加一个root.jpg,root.xml和root.txt文件。我们还在大文件目录中添加了一个largefile.jpg,largefile.xml和largefile.txt。提交这些文件,并使用以下命令我们可以验证将哪些文件作为Git LFS文件进行跟踪:

$ git lfs ls-files
0282cb373a * largefiles/largefile.jpg
fc3b142235 * largefiles/largefile.xml
72d5491269 * root.jpg

此结果完全符合我们的预期:Git LFS跟踪所有jpg文件,Git LFS仅跟踪largefiles目录中的xml文件,而不是我们的root.xml文件和两个txt文件。当您查看文件系统上的文件时,无论Git LFS跟踪的文件与否之间都没有任何区别。这是因为Git LFS过滤器将指针文件替换为实际内容。这样,Git LFS的使用对您作为用户是透明的。

现在将所有内容推送到远程存储库。当您在GitHub上单击Git LFS文件时,该文件将正常显示,但在文件顶部表示该文件已存储为Git LFS文件。

 现有git仓库中使用Git LFS

到目前为止,我们已经展示了如何在启动新存储库时启用Git LFS,并且知道我们要与Git LFS关联的文件。但是,如果要对现有存储库启用Git LFS,该怎么办?您可以像对新存储库一样进行操作。从那时起,Git LFS将跟踪新文件或文件更新。启用Git LFS之前的提交不会自动迁移。但是,有一种方法可以迁移整个存储库。您必须通过以下命令迁移所有现有分支:

git lfs migrate import --include="*.jpg,largefiles/*.xml" --include-ref=refs/heads/master

上面的示例显示了如果我们忘记将任何文件类型关联到我们先前创建的存储库时应该使用的命令。在include选项之后,您指定必须迁移的文件类型,在include-ref选项之后,您要迁移的分支。此后,您的历史记录将被迁移到LFS。但请注意,此migrate命令还将重写您的历史记录!您的存储库历史记录将具有不同的提交哈希值,因此每个开发人员都应在执行此操作后重新克隆存储库。在执行此迁移之前,请仔细考虑后果。

提示

  • 本地Git LFS缓存不会自动清除。就像您必须定期修剪远程分支一样,您还必须使用以下命令修剪Git LFS内容:git lfs prune
  • 确保所有开发人员都安装了Git LFS。当没有安装Git LFS的人提交了应与Git LFS相关联的文件时,您会得到一些奇怪的错误。它们可以固定,但是最好防止这种情况的发生。
  • 我们还提到了将二进制文件提交到Git存储库,但建议这样做吗?作为第一个答案,我会拒绝。但是有时您只是没有有效的选择。在考虑提交二进制文件时,请考虑以下事项:
    • 真的有必要将二进制文件置于版本控制之下吗?
    • 二进制文件有基于文本的替代方法吗?例如,假设您要提交MS Word文件,是否可以将它们转换为纯文本,或者是否存在有效的参数?
CI / CD获得的10大优势
如何告诉git本地分支跟踪远程分支?