git对象模型

在git系统中有四种类型的对象,所有的Git操作都是基于这四种类型的对象:
"blob":这种对象用来保存文件的内容。
"tree":可以理解成一个对象关系树,它管理一些"tree"和“blob”对象。
"commit":指向一个"tree",它用来标记项目某一个特定时间点的状态。它包括以下关于时间点的元数据,如时间戳、最近一次提交的作者、指向上次提交等。
"tag":给某个提交增添一个标记。

SHA1哈希值

在Git系统中,每个Git对象都有一个特殊的ID来代表这个对象,这个特殊的ID就是我们所说的SHA1哈希值。SHA1哈希值是通过SHA1算法计算出来的哈希值,对于内容不同的对象,会有不同的SHA1哈希值。

实例

我们以这样的目录结构为例来研究,
--repository      //根目录文件夹
  --a.txt        //txt文件,初始时,内容为a_git
  --bb          //文件夹
    --b.txt        //txt文件,在bb文件夹下面,内容为b_git

首先cd repository目录,初始化使用git init命令,执行了这个命令后repository目录下会生成一个.git文件夹,使用find . -type f命令查看目录结构:

然后执行git add -A和git commit -m "commit1"两条命令,可以看到.git/objects/文件夹下增加了五个对象

可是我们的示例工程只有两个文件和一个文件夹,为什么objects里却有五个文件那,这里就要说说commit类型了,commit类型内部可以引用一个tree类型文件和一个commit类型文件。

关于文件的名字,objects内部的文件全部是以sha-1命名,如果是blob类型则以文件内容做sha-1计算得出40字符的校验和,然后为了不让这个objects内部文件过多,所以使用40字符的前两位来建立一个文件夹,在以后38位为文件名,包括commit 和tree 全部使用sha-1校验和来命名。

接下来说一下这五个文件是以什么结构关联的:
每个commit 引用一个tree,根据工程目录结构这个tree 再引用一个blob(a.txt)和一个tree(bb) ,这个tree(bb)则引用一个blob(b.txt)如图:

通过这个图就可以看出来commit,tree,blob的关系了,也基本能明白为什么objects下有五个文件了, 现在我改动一下a.txt然后在提交一个版本,在a.txt添加"123456"内容然后执行add和commit,添加一个版本,接下来再看objects内部的情况:

比刚刚多了三个文件,究竟是哪三个文件?因为我们改动了a.txt文件,所以这里在保留上一个版本的a.txt的基础上新增加一个a.txt文件,git只对有改动的文件进行备份保留。另外两个文件分别是commit 2和一个根tree,现在这8个文件的关系如图:

commit文件内部可以引用一个commit,这样commit之间就可以建立关系了,因为只有a.txt文件做了改动所以只有a.txt文件新建了一个,然后被commit2引用,bb和b.txt文件未做改动则commit2依然引用之前的文件。同理如果我们再改动b.txt文件,我们可以设想一下这些文件的关联关系。如图:

branch分支

git branch 可以获取当前的分支列表,这个分支列表会保存在./git/refs/heads/这个路径下,这里包含master和一些其他分支文件,以master文件为例查看master文件内容如下:

其实这是一个commit类型 的文件名,这样每个分支都可以拥有一个自己的commit引用,从上面的图可以看出只要拿到commit的文件名就可以找到所有跟他关联的文件,还有个问题是./git/refs/heads/这个文件下是所有分支信息,总要有一个当前分支,其实这个当前分支是被记录在./git/HEAD文件内部:

因为当前是master分支所以HEAD文件里记录的是master,每次我们使用git checkout 来切换分支的时候就是在修改HEAD这个文件的内容。那么我们基本就可以理解:我们首先选择一个分支为当前分支,每个分支里记录着当前分支最顶端的commit对象,这个commit对象又可以找到所有跟它关联tree和blob,同时commit对象又和它的历史commit关联。我们可以任意切换当前分支,同时又可以修改当前分支指向的commit对象,比如我们执行reset可以选择回退到任意一个commit。这些就可以顺理成章切换任意分支并且找到任意版本的文件了。

git底层原理(二)的更多相关文章

  1. iOS 技术篇:从使用到了解block底层原理 (二)

    block实质 序言 上篇文章中主要通过简单的demo展示了block的使用场景,本篇将基于上篇文章iOS 技术篇:从使用到了解block底层原理 (一)进一步了解block底层的实现原理. bloc ...

  2. [置顶] Asp.Net底层原理(二、写自己的Asp.Net框架)

    我们介绍过了浏览器和服务器之间的交互过程,接下来介绍Asp.net处理动态请求. 写自己的Asp.Net框架,我们不会引用System.Web这个程序集,我们只需要创建要给自己的类库,所以在接下来的程 ...

  3. git底层原理(一)

    1.git仓库的初始化: 输入git init指令,会看到在当前空目录下创建了一个.git隐藏文件夹,这个就是git实现一切版本管理的关键.进入到.git目录下,里面包含三个文件(config/des ...

  4. git的核心命令使用和底层原理解析

    文章目录: GIT体系概述 GIT 核心命令使用 GIT 底层原理 一.GIT体系概述 GIT 与 svn 主要区别: 存储方式不一样 使用方式不一样 管理模式不一样 1.存储方式区别 GIT把内容按 ...

  5. 深入源码分析SpringMVC底层原理(二)

    原文链接:深入源码分析SpringMVC底层原理(二) 文章目录 深入分析SpringMVC请求处理过程 1. DispatcherServlet处理请求 1.1 寻找Handler 1.2 没有找到 ...

  6. 【Spring Data JPA篇】JPA的底层原理(二)

    一.接口继承结构 二.底层原理

  7. 【T-SQL进阶】02.理解SQL查询的底层原理

    本系列[T-SQL]主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础]02.联接查询 [T-SQL基础]03.子查询 [T-SQL基础]04.表表达式 ...

  8. Git详解之九:Git内部原理

    Git 内部原理 不管你是从前面的章节直接跳到了本章,还是读完了其余各章一直到这,你都将在本章见识 Git 的内部工作原理和实现方式.我个人发现学习这些内容对于理解 Git 的用处和强大是非常重要的, ...

  9. 想晋级高级工程师只知道表面是不够的!Git内部原理介绍

    本文由云+社区发表 作者:腾讯工蜂用户:王二卫 从不一样的视角了解git,以便更好的使用git 一.git & git 版本库认识 git 是一个内容寻址的文件系统,其核心部分是一个简单的键值 ...

随机推荐

  1. 《Algorithms Unlocked》读书笔记1——循环和递归

    <Algorithms Unlocked>是 <算法导论>的合著者之一 Thomas H. Cormen 写的一本算法基础. 书中没有涉及编程语言,直接用文字描述算法,我用 J ...

  2. oracle分区表的建立方法(包含已经存在的表要分区)分享,非常好

    非原创 Oracle提供了分区技术以支持VLDB(Very Large DataBase).分区表通过对分区列的判断,把分区列不同的记录,放到不同的分区中.分区完全对应用透明. Oracle的分区表可 ...

  3. 拍照、本地图片工具类(兼容至Android7.0)

    拍照.本地图片工具类:解决了4.4以上剪裁会提示"找不到文件"和6.0动态授予权限,及7.0报FileUriExposedException异常问题. package com.hb ...

  4. MongDB系列(一):使用node.js连接数据库

    1.首先启动mongodb数据库服务器 2.创建app.js,代码如下: /** * Created by byzy on 2016/8/18. * node.js 连接 mongodb实例 */ / ...

  5. Elasticsearch实现类似 like '?%' 搜索

    在做搜索的时候,下拉联想词的搜索肯定是最常见的一个场景,用户在输入的时候,要自动补全词干,说得简单点,就是以...开头搜索,如果是数据库,一句SQL就很容易实现,但在elasticsearch如何实现 ...

  6. 浅谈聚类算法(K-means)

    聚类算法(K-means)目的是将n个对象根据它们各自属性分成k个不同的簇,使得簇内各个对象的相似度尽可能高,而各簇之间的相似度尽量小. 而如何评测相似度呢,采用的准则函数是误差平方和(因此也叫K-均 ...

  7. vue实现全选效果

    vue实现全选效果 接触vue快半年了,记得刚用vue做项目的时候遇到一个全选功能,当时到处百度也没有找到怎么实现,最后还是用了jquery进行dom操作实现的. 今天没事就顺手写了一个,感觉很简单, ...

  8. std::thread使用

    本文将从以下三个部分介绍C++11标准中的thread类,本文主要内容为: 启动新线程 等待线程与分离线程 线程唯一标识符 1.启动线程 线程再std::threada对象创建时启动.最简单的情况下, ...

  9. LinkCode 下一个排列、上一个排列

    http://www.lintcode.com/zh-cn/problem/next-permutation-ii/# 原题 给定一个若干整数的排列,给出按正数大小进行字典序从小到大排序后的下一个排列 ...

  10. split()方法

    split()方法用于把一个字符串分隔成字符串数组. 它有两个参数: separator:从参数指定的地方分隔字符串,必需: howmany:该参数可指定返回的数组的最大长度.如果设置了该参数,返回的 ...