git-lfs大文件存储OSS或 git lfs私服

819 阅读3分钟

今天来聊一聊GIT LFS存储方案

先来说明一下为什么需要自定义LFS API 机制,存储到OSS/私服类场景。 国内的阿里云/OSChina等都提供免费的代码仓库,但是针对仓库基本上都是有存储容量的限制,大文件存储提交时,经常会提示超过200MB,不允许提交等场景。通过此方案可以实现将仓库里面的代码存储到OSS,也就是代码仓库我们继续使用阿里云/OSchina, 但是大文件存储,我们单独配置,实现自定义存储机制。

基础知识

Git Large File Storage(简称 Git LFS)是一个由 GitHub 开发的 Git 扩展,用于更有效地处理大型文件。在标准的 Git 版本控制系统中,所有的文件变更都会被存储为差异(diff),这意味着即使是大型文件的微小变更也会导致整个文件被重新存储。这在处理大型文件(如视频、音频、大型二进制文件等)时会导致仓库迅速膨胀,并且使得克隆和同步仓库变得非常缓慢和低效。

使用 Git LFS,你可以更高效地管理大型文件,同时保持 Git 的灵活性和版本控制的优势。

项目中如何使用GIT LFS配置

针对项目根目录,增加配置文件 .gitattributes ,配合 Git LFS 使用,告诉 Git 使用 Git LFS 来处理大文件。

*.png filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.rpm filter=lfs diff=lfs merge=lfs -text
*.deb filter=lfs diff=lfs merge=lfs -text

*.exe filter=lfs diff=lfs merge=lfs -text
*.msi filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.rar filter=lfs diff=lfs merge=lfs -text
*.apk filter=lfs diff=lfs merge=lfs -text

以上是告诉GIT仓库,如何处理大文件机制, 是将png/zip/rpm/deb类文件类型,通过大文件存储来实现。

如果我们使用的是阿里云的云效代码仓库,我们针对lfs配置后,提交代码,代码仓库大文件存储,会自动生效,并将相关文件配置的后缀,自动同步到大文件存储中去。 如下所示:

image.png

Git LFS OSS/私服数据存储方案

针对Git LFS,基于HTTP协议, 我们可以实现自己的大文件存储方案到OSS存储或者私服存储解决。

也就是我们基于LFS API , 实现自己的LFS Config配置,即可基于当前仓库源,同步大文件存储仓库。

具体官方API地址 : github.com/git-lfs/git…

大概思路是: 增加HTTP 协议接口,告知GIT LFS 上传机制和下载机制。

Git LFS API接口对接

本身实现代码如下:(JAVA)

@RequestMapping("/upload/{oid}")
public void upload(
    @PathVariable String oid, HttpServletRequest request, HttpServletResponse response)
    throws IOException {
  Map<String, String> headerMap = JakartaServletUtil.getHeaderMap(request);
  Map<String, String> paramsMap = JakartaServletUtil.getParamMap(request);

  try (InputStream inputStream = request.getInputStream();
      ByteArrayInputStream byteArrayInputStream =
          new ByteArrayInputStream(inputStream.readAllBytes())) {
    Console.log("upload header:{}", JSONUtil.toJsonStr(headerMap));
    Console.log("upload params:{}", JSONUtil.toJsonStr(paramsMap));

    BitifulOssLib.putObject(oid, byteArrayInputStream);
    response.setCharacterEncoding("utf-8");
    response.setContentType(ContentType.JSON.getValue());

    PrintWriter writer = response.getWriter();
    writer.write("ok");

    writer.flush();
    writer.close();
  }
}

@RequestMapping("/objects/batch")
public void objectsBatch(HttpServletRequest request, HttpServletResponse response)
    throws IOException {
  Map<String, String> headerMap = JakartaServletUtil.getHeaderMap(request);
  Map<String, String> paramsMap = JakartaServletUtil.getParamMap(request);
  String requestBody = JakartaServletUtil.getBody(request);

  // NoSuchMethodError javax.servlet.http.HttpServletMapping
  // javax.servlet.http.HttpServletRequest.getHttpServletMapping()

  Console.log("objects_batch header:{}", JSONUtil.toJsonStr(headerMap));
  Console.log("objects_batch params:{}", JSONUtil.toJsonStr(paramsMap));
  Console.log("objects_batch requestBody:{}", requestBody);

  Document uploadDoc = DocuLib.parse(requestBody);

  String authorization = StringLib.toStr(headerMap.get("authorization"), "");
  String operation = DocuLib.getStr(uploadDoc, "operation");
  List<Document> objectsList = DocuLib.getList(uploadDoc, "objects");

  switch (operation) {
    case "upload":
      objectsList = gitLfsApiService.upload(authorization, objectsList);
      break;
    case "download":
      objectsList = gitLfsApiService.download(authorization, objectsList);
      break;
  }

  Document responseDoc =
      new Document().append("transfer", "basic").append("objects", objectsList);

  response.setCharacterEncoding("utf-8");
  response.setContentType("application/vnd.git-lfs+json");

  PrintWriter writer = response.getWriter();
  writer.write(JSONUtil.toJsonStr(responseDoc));

  writer.flush();
  writer.close();
}

Git配置增加.lfsconfig 配置文件,将LFS对接调整到指定服务

操作命令如下:

git config -f .lfsconfig lfs.url "针对LFS API实现的自己的HTTP接口地址" "basic"

GIt LFS 授权/权限控制

通过自己实现的LFS接口,需做好权限控制,以上是我自己调通的部分,针对权限机制,可基于代码层自行做好控制即可。

最终呈现(个人版)

将仓库大文件存储到缤纷云,阿里云效仅存储代码,不存储大文件

image.png