zoukankan      html  css  js  c++  java
  • git原理探索实验1——git的三种对象

    背景知识

    git的三个区域

    • working directory
      • 也就是你当前所能操作的那些目录和文件
    • history
      • 你所提交的所有记录,文件历史内容等等。git是个分布式版本管理系统,在你本地有项目的所有历史提交记录;文件历史记录;提交日志等等
    • stage(index)
      • 暂存区域
      • 本质上是个文件,也就是.git/index

    git的三类对象及其关系

    • commit对象
      • 用于表示一个提交
      • commit对象之间会组织成一棵树的结构
      • 每一次提交都会产生一个commit对象
      • 除了第一次提交产生的commit对象,其它的commit对象都会有父亲commit对象
      • 如果只是提交操作,则父亲节点只有1个
      • 如果是merge操作,则父亲节点会有2个
      • commit对象包含的信息有
        • parent,父亲提交对象
        • tree, 根目录树对象
        • author,作者
        • committer,提交者
    • tree对象
      • 用于表示一个目录
    • blob对象
      • 用于表示一个文件
      • tree和blob对象可以看成是git内部采用的文件系统对象
      • 其组织结构和文件系统是很像的,很好理解
    • 这些对象都保存在.git/objects/目录下,每一个对象都会生成1个40位的哈希值,前2位作为文件夹,后38位作为文件名
    • 不同名,相同内容的文件,其哈希值相同,其blob对象也是共用的

    实验1

    $ git init test
    Initialized empty Git repository in C:/Users/MilesGO/Desktop/git/test/.git/
    $ cd test
    $ find .git/objects -type f
    

    此时由于没有任何的提交记录, find .git/objects -type f指令的返回结果为空,这条指令会列出.git/objects目录下的所有文件
    接下来在根目录下创建一个README文件,文件内容hello git

    $ echo 'hello git' >> README
    find .git/objects -type f
    

    返回结果仍然为空,说明在工作区域做出的改变,如果没有提交到暂存区或历史版本库,是不会产生任何的git对象的

    git add README
    $ find .git/objects -type f
    .git/objects/8d/0e41234f24b6da002d962a26c2495ea16a425f
    $ git cat-file -t 8d0e4123
    blob
    $ git cat-file -p 8d0e4123
    hello git
    

    git cat-file -t指令可以查看一个git对象的类型,git cat-file -p指令可以查看一个git对象的内容
    我们将README文件添加到暂存区之后,生成了一个blob文件,对应了暂存区中的README,其内容就是我们刚刚添加的hello git
    接下来我们将暂存区的README提交

    $ git commit -m 'add README'
    [master (root-commit) 29c0715] add README
     1 file changed, 1 insertion(+)
     create mode 100644 README
    
    $ find .git/objects -type f
    .git/objects/28/324fe5bad6e397de7a37aa7d8c94b6bf176b83
    .git/objects/29/c07152991c7b3ee41f9cb5ac1eff1f26610665
    .git/objects/8d/0e41234f24b6da002d962a26c2495ea16a425f
    
    $ git cat-file -t 28324fe5
    tree
    
    $ git cat-file -t 29c07152
    commit
    

    可以看到新生成了1个commit对象和一个tree对象,分别查看这两个对象的内容

    $ git cat-file -p 29c07152
    tree 28324fe5bad6e397de7a37aa7d8c94b6bf176b83
    author MilesGO <164173218@qq.com> 1560070361 +0800
    committer MilesGO <164173218@qq.com> 1560070361 +0800
    
    add README
    

    commit对象表明了其对应的根目录tree为28324f,也就是刚才新生成的tree对象

    $ git cat-file -p 28324f
    100644 blob 8d0e41234f24b6da002d962a26c2495ea16a425f    README
    

    这个tree对象中只包含了一个blob对象8d0e41,也就是一开始我们添加的README文件

    实验2

    在实验1的基础上继续进行
    在README文件中添加hello git again,commit后查看git对象情况

    $ echo 'hello git again' >> README
    $ git add README
    $ git commit -m 'modify README'
    [master 4a1d754] modify README
     1 file changed, 1 insertion(+)
    
    $ find .git/objects -type f
    .git/objects/28/324fe5bad6e397de7a37aa7d8c94b6bf176b83
    .git/objects/29/c07152991c7b3ee41f9cb5ac1eff1f26610665
    .git/objects/4a/1d75425a4cd5c3e206a4c69415c59802175039
    .git/objects/8d/0e41234f24b6da002d962a26c2495ea16a425f
    .git/objects/b9/641c1bd3e89e43cfaebf63305fc0a655635b50
    .git/objects/f8/3422c24917dcb2c2f781c08d83ac2fbc363dd2
    
    $ git cat-file -t 4a1d75
    commit
    $ git cat-file -t b9641c
    tree
    $ git cat-file -t f83422
    blob
    

    分别新增了1个commit,1个tree和1个blob对象

    $ git cat-file -p 4a1d75
    tree b9641c1bd3e89e43cfaebf63305fc0a655635b50
    parent 29c07152991c7b3ee41f9cb5ac1eff1f26610665
    author MilesGO <164173218@qq.com> 1560070808 +0800
    committer MilesGO <164173218@qq.com> 1560070808 +0800
    
    modify README
    

    新的提交必然需要生成1个新的提交对象,其tree根目录对象为b9641c,也是新生成的,其parent对象为29c071,也就是第一次提交生成的提交对象

    $ 100644 blob f83422c24917dcb2c2f781c08d83ac2fbc363dd2    README
    $ git cat-file -p b9641c
    

    新生成的tree对象中,包含1条blob对象的信息

    $ git cat-file -p f83422
    hello git
    hello git again
    

    该blob对象也就是我们刚才修改后提交的README
    到此为止,一共有2个commit对象,2个tree对象,2个blob对象

    实验3

    创建src目录,在src目录下添加main.cpp,添加一些内容

    $ mkdir src
    $ echo 'hello world' >> src/main.cpp
    $ git add --a
    $ git commit -m 'add src/main.cpp'
    [master 12c2c80] add src/main.cpp
     1 file changed, 1 insertion(+)
     create mode 100644 src/main.cpp
    
    $ find .git/objects -type f
    .git/objects/12/c2c80788dcd74a1cd739157c0a1011514d36b2
    .git/objects/28/324fe5bad6e397de7a37aa7d8c94b6bf176b83
    .git/objects/29/c07152991c7b3ee41f9cb5ac1eff1f26610665
    .git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad
    .git/objects/3f/68ce3f72d2ee5bec285180c6fb0aa3a7eee4ff
    .git/objects/4a/1d75425a4cd5c3e206a4c69415c59802175039
    .git/objects/8d/0e41234f24b6da002d962a26c2495ea16a425f
    .git/objects/b9/641c1bd3e89e43cfaebf63305fc0a655635b50
    .git/objects/c5/fb7c2c039f5f48bf89f922267016e8702bead8
    .git/objects/f8/3422c24917dcb2c2f781c08d83ac2fbc363dd2
    
    

    新添加的对象有

    12c2c8
    3b18e5
    3f68ce
    c5fb7c
    

    查看这些新添加的对象

    $ git cat-file -t 12c2c8
    commit
    $ git cat-file -p 12c2c8
    tree 3f68ce3f72d2ee5bec285180c6fb0aa3a7eee4ff
    parent 4a1d75425a4cd5c3e206a4c69415c59802175039
    author MilesGO <164173218@qq.com> 1560071508 +0800
    committer MilesGO <164173218@qq.com> 1560071508 +0800
    
    add src/main.cpp
    
    $ git cat-file -t 3b18e5
    blob
    $ git cat-file -p 3b18e5
    hello world
    
    $ git cat-file -t 3f68ce
    tree
    $ git cat-file -p 3f68ce
    100644 blob f83422c24917dcb2c2f781c08d83ac2fbc363dd2    README
    040000 tree c5fb7c2c039f5f48bf89f922267016e8702bead8    src
    
    $ git cat-file -t c5fb7c
    tree
    $ git cat-file -p c5fb7c
    100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad    main.cpp
    
    

    实验4

    不同文件名,相同文件内容

    $ echo 'hello world' >> main2.cpp
    $ git add main2.cpp
    $ git commit -m 'add main2.cpp'
    [master 314b549] add main2.cpp
     1 file changed, 1 insertion(+)
     create mode 100644 main2.cpp
    

    在这种情况下,会新增哪些git对象呢?

    $ find .git/objects -type f
    .git/objects/12/c2c80788dcd74a1cd739157c0a1011514d36b2
    .git/objects/28/324fe5bad6e397de7a37aa7d8c94b6bf176b83
    .git/objects/29/c07152991c7b3ee41f9cb5ac1eff1f26610665
    .git/objects/31/4b5494eb06a9963f4e6f97075f2354c8a15f13
    .git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad
    .git/objects/3e/c767e93a78c0ef5c4685eace73192bf6bc6848
    .git/objects/3f/68ce3f72d2ee5bec285180c6fb0aa3a7eee4ff
    .git/objects/4a/1d75425a4cd5c3e206a4c69415c59802175039
    .git/objects/8d/0e41234f24b6da002d962a26c2495ea16a425f
    .git/objects/b9/641c1bd3e89e43cfaebf63305fc0a655635b50
    .git/objects/c5/fb7c2c039f5f48bf89f922267016e8702bead8
    .git/objects/f8/3422c24917dcb2c2f781c08d83ac2fbc363dd2
    

    其中314b54和3ec767是新增的

    $ git cat-file -t 314b54
    commit
    $ git cat-file -p 314b54
    tree 3ec767e93a78c0ef5c4685eace73192bf6bc6848
    parent 12c2c80788dcd74a1cd739157c0a1011514d36b2
    author MilesGO <164173218@qq.com> 1560072040 +0800
    committer MilesGO <164173218@qq.com> 1560072040 +0800
    
    add main2.cpp
    
    $ git cat-file -t 3ec767
    tree
    
    $ git cat-file -p 3ec767
    100644 blob f83422c24917dcb2c2f781c08d83ac2fbc363dd2    README
    100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad    main2.cpp
    040000 tree c5fb7c2c039f5f48bf89f922267016e8702bead8    src
    
    $ git cat-file -p c5fb7c
    100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad    main.cpp
    

    main2.cpp和src/main.cpp共用了同一个blob对象

    git ls-files --stage可以看到暂存区所有文件及其对应的blob文件

    $ git ls-files --stage
    100644 f83422c24917dcb2c2f781c08d83ac2fbc363dd2 0       README
    100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad 0       main2.cpp
    100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad 0       src/main.cpp
    

    从这里也可以看到main2.cpp和src/main.cpp共用了同一个blob对象

  • 相关阅读:
    Redis集群(一)
    Mysql分库分表
    Redisson分布式锁
    Spring Cloud Eureka 高可用
    Spring RestTemplate具备负载均衡功能
    Redis分布式锁
    B树/B-树/B+树/B*树的数据库应用
    ABAC访问控制模型
    Maven自定义打包的包名
    Versions maven plugin 修改版本
  • 原文地址:https://www.cnblogs.com/milesgo517/p/10993618.html
Copyright © 2011-2022 走看看