Git大文件存储背后的存储机制是什么?

Tar*_*wal 3 git github

Github最近推出了一个扩展 git,用于以不同的方式存储大文件.扩展名究竟是什么意思用Git中的文本指针替换大文件

Von*_*onC 9

您可以在git-lfs源中看到如何定义"文本指针":

type Pointer struct {
    Version string
    Oid     string
    Size    int64
    OidType string
} 
Run Code Online (Sandbox Code Playgroud)

污迹清洁源的手段git-lfs可以使用内容过滤器驱动程序,以便:

  • 在结帐时下载实际文件
  • 在提交时将它们存储在外部源中.

查看指针规格:

核心Git LFS的想法是,不是将大blob写入Git存储库,而是只写入指针文件.

version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345
(ending \n)
Run Code Online (Sandbox Code Playgroud)

Git LFS需要一个URL端点与远程服务器通信.
Git存储库可以为不同的远程控制器提供不同的Git LFS端点.

实际文件将上载到或从符合Git-LFS API的服务器下载.

git-lfs手册确认了这一点,该手册提到:

实际文件被推送到Git LFS API

您需要一个实现该API的Git服务器,以支持上载和下载二进制内容.


关于内容过滤器驱动程序(它存在于Git中很长一段时间,远在lfs之前,并且在这里被lfs用来添加这个"大文件管理"功能),这是大部分工作发生的地方:

当文件从Git存储库检出到工作目录时,涂抹过滤器运行.
Git将Git blob的内容作为STDIN发送,并期望内容以STDOUT的形式写入工作目录.

读100个字节.

  • 如果内容是ASCII并且与指针文件格式匹配:
    在.git/lfs/objects/{OID}中查找文件.

  • 如果不存在,请从服务器下载.
    将其内容读入STDOUT

  • 否则,只需通过STDOUT传递STDIN.

清洁过滤器运行的文件添加到资料库.
Git将要添加的文件的内容发送为STDIN,并期望内容作为STDOUT写入Git.

  • 将二进制内容从STDIN流式传输到临时文件,同时计算其SHA-256签名.
  • 检查文件.git/lfs/objects/{OID}.
  • 如果它不存在:
    • 将OID排队以进行上传.
    • 将临时文件移动到.git/lfs/objects/{OID}.
  • 删除临时文件.
  • 将指针文件写入STDOUT.

Git 2.11(2016年11月)有一个详细说明如何工作的提交:提交edcc858,由Martin-Louis Bright帮助并签署:Lars Schneider.

convert:添加filter.<driver>.process选项

Git的清理/涂抹机制为每个受过滤器影响的blob调用外部过滤器进程.如果Git过滤了大量blob,那么外部过滤器进程的启动时间可能会成为整个Git执行时间的重要部分.

在初步性能测试中,这个开发人员使用golang编写的clean/smudge过滤器来过滤12,000个文件.这个过程使用现有的过滤机制需要364s,使用新机制需要5s.在这里查看详细信息:git-lfs/git-lfs#1382

此补丁添加了filter.<driver>.process字符串选项,如果使用该选项,则使外部过滤器进程保持运行,并使用基于数据包格式(pkt-line)的协议处理所有blob,而不是标准输入和标准输出.
详细解释了完整的协议Documentation/gitattributes.txt.

一些关键决定:

  • 长时间运行的过滤器过程称为过滤器协议版本2,因为现有的单次过滤器调用被视为版本1.
  • Git发送一条欢迎消息,并在外部过滤器进程启动后立即收到响应.如果版本1过滤器与filter.<driver>.process版本2过滤器的选项不正确使用,这可确保Git不会挂起 .此外,Git可以检测到这种错误并警告用户.
  • 过滤操作的状态(例如"成功"或"错误")在实际响应之前设置,并且(如果需要!)在响应之后重新设置.这个两步状态响应的优点是如果过滤器检测到错误早期,然后过滤器可以进行通信,Git甚至不需要创建结构来读取响应.
  • 所有状态响应都是以flush数据包终止的pkt-line列表.这允许我们将来发送具有相同协议的其他状态字段.

这导致Git 2.12(2017年第一季度)发出警告

请参阅提交7eeda8b(2016年12月18日),并由Lars Schneider()提交c6b0831(2016年12月3日).(由Junio C Hamano合并- -提交08721a0,2016年12月27日)larsxschneider
gitster

docs:警告可能' ='在清洁/涂抹过滤器过程值

clean/smudge过滤器进程" key=value"对中的路径名值可以包含' ='字符(在edcc858中引入).
让用户在文档中了解此问题,添加相应的测试用例,并在示例实现的过滤器进程值解析器中修复该问题contrib.