zoukankan      html  css  js  c++  java
  • git对象存储

    之前提到当存储数据内容时,会在objects文件夹下存储一个git对象。我们花些时间来看看 Git 是如何存储对象的。你将看来如何通过 Ruby 脚本语言存储一个 blob 对象 ,有必要了解一下对象是如何被存储的。以git设计哲学中的test1.txt为例分析blob对象如何被计算校验和?如何被存储?是否和直接调用git命令的结果一致?

    sha-1校验和计算

    我们需要验证通过ruby计算出来的检验和与这个一致。

    为了验证,新建一个git仓库

    $ mkdir blobtest
    $ cd blobtest

     $ git init
     Initialized empty Git repository in /Users/lyc/Desktop/tg/.git/

    同样新建一个文件test1.txt,内容为test1,并把它加入暂存区
     
    $ echo test1 > test1.txt
    $ git add test1.txt

    gitt使用'blob ' + len(content) + '' + content作为文件内容
    blob表示对象类型为blob类型,

    len表示内容的长度

    为空字节

    其中'blob ' + len(content) + '' 来组成一个header,然后再将这个header与真正的内容拼接起来,并计算拼接后的新内容的 SHA-1 校验和。

    使用 irb 命令进入 Ruby 交互式模式:

    $ irb
    irb(main):001:0> content = "test1
    "
    => "test1
    "
    irb(main):002:0> header = "blob #{content.length}"
    => "blob 6u0000"
    irb(main):003:0>  store = header + content
    => "blob 6u0000test1
    "
    irb(main):004:0>   require 'digest/sha1'
    => true
    irb(main):005:0> sha1 = Digest::SHA1.hexdigest(store)
    => "a5bce3fd2565d8f458555a0c6f42d0504a848bd5"

    可见计算出来的校验后与刚开始设定的校验和是一致的。

    git对象存储

    git设计哲学中我们了解到test1.txt被git add命令添加到git仓库后,存储的路径如下

    .git/
    |--index
    |--objects
    |   |--a5
    |   |   |-- bce3fd2565d8f458555a0c6f42d0504a848bd5

    我们通过ruby命令来对数据进行压缩然后存储,看看会发生什么。

    Git 用 zlib 对数据内容进行压缩,在 Ruby 中可以用 zlib 库来实现。

    irb(main):006:0> require 'zlib'
    => true
    irb(main):007:0> zlib_content = Zlib::Deflate.deflate(store)
    => "xx9CKxCAxC9OR0c(I-.1xE4x02x00x1DxC5x03xF1"

    最后将用 zlib 压缩后的内容写入磁盘。

    git的存储的规则是:sha1值的前2位作为文件夹名,后38位作为文件名

    irb(main):008:0> path = '.git/objects/' + sha1[0,2] + '/' + sha1[2,38]
    => ".git/objects/a5/bce3fd2565d8f458555a0c6f42d0504a848bd5"
    irb(main):009:0>  require 'fileutils'
    => true
    irb(main):010:0> FileUtils.mkdir_p(File.dirname(path))
    => [".git/objects/a5"]
    irb(main):011:0> File.open(path, 'w') { |f| f.write zlib_content }
    => 21

    把它存储在.git的objects目录下

    .git/
    |--index
    |--objects
    |   |--a5
    |   |   |-- bce3fd2565d8f458555a0c6f42d0504a848bd5

    这样就完成了一次blob对象的创建。

    退出irb后,用git命令验证下创建对象的内容

    $ git cat-file -p a5bce3fd2565d8f458555a0c6f42d0504a848bd5
    test1

    结果与test1.txt的内容一致。

    执行git st命令查看下状态,

    $ git st
    On branch master
    
    Initial commit
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
        test1.txt

    发现是untracked

    再用git add命令

    $ git st
    On branch master
    
    Initial commit
    
    Changes to be committed:
      (use "git rm --cached <file>..." to unstage)
    
        new file:   test1.txt

    再看.git/objects目录下,目录没变,还是

    .git/
    |--index
    |--objects
    |   |--a5
    |   |   |-- bce3fd2565d8f458555a0c6f42d0504a848bd5

    结论:Git 以对象类型为起始内容构造一个文件头,本例中是一个 blob。然后添加一个空格,接着是数据内容的长度,最后是一个空字节 (null byte),接着用这个文件头和真正的内容拼接起来(不是文件名)计算校验和,然后用zlib对数据进行压缩,按照SHA-1 值的头两个字符作为子目录名称,剩余 38 个字符作为文件名保存压缩后的数据。这样就把一个文件存储到了git仓库中。

    出处

  • 相关阅读:
    011 处理模型数据时@ModelAttribute的使用
    动态产生DataSource------待整理
    连接池问题
    maven加载第三方jar不能加载
    010 处理模型数据(ModelAndView,Map Model,@SessionAttributes)
    009 使用servlet API作为参数
    008 使用POJO对象绑定请求参数
    007 @CookieValue绑定请求中的cookie
    006 请求处理方法签名
    005 RequestMapping_HiddenHttpMethodFilter 过滤器
  • 原文地址:https://www.cnblogs.com/lycokcc/p/4882356.html
Copyright © 2011-2022 走看看