Git是一个开源的分布式版本控制系统,是目前主流的版本控制系统,很多软件项目都会用它做源代码管理。Git的常用操作想必很多人都会,但是可能了解Git内部原理的人并不多。了解一些底层的东西,可以更好的帮你理清思路,遇到问题的时候也可以更好的去解决。

准备工作

在介绍Git如何存储数据之前,我们先做一些准备工作。

首先新建一个目录git-test,然后在这个目录右键,打开Git Bash,

然后,在Git Bash,分别执行以下命令,

$ git init
$ echo 'a' > a.txt
$ echo 'b' > b.txt
$ git add .

至此,准备工作完成。我们可以看到,git-test目录下现在有一个.git目录,以及两个txt文件(a.txt、b.txt)。

Git如何存储数据

.git目录是git init后在当前目录生成的一个管理git仓库的目录,这里包含所有git操作所需要的东西。其中objects目录下存放所有的git对象。经过上面的操作后,objects目录是这样的,

其中info和pack目录是执行git init以后就已经有的,而78和61目录分别对应着a.txt和b.txt文件,这两个目录是创建了a.txt和b.txt,并执行git add .命令后才生成的。

78目录下有一个文件,查看一下这个文件的内容,执行以下命令,

$ cat .git/objects/78/981922613b2afb6025042ff6bd878ac1994e85

我们看到文件的内容是一串乱码,这是因为Git将信息压缩成二进制。Git提供了一个能够帮助探索objects的命令:git cat-file [-t] [-p], -t可以查看object的类型,-p可以查看object存储的具体内容。分别执行以下命令,

$ git cat-file -t 7898
$ git cat-file -p 7898

blob类型的object

7898就是目录名加上文件名的前两位。可以看到,这个object是一个blob类型的object,而这个object存储的内容,就是我们写入到a.txt的文本。因此,上面的乱码其实就是a.txt的内容,也就是说,这个object存储着a.txt文件的内容。

blob类型的object存储的是一个文件的内容。然后,Git根据这个文件的内容经过SHA1哈希算法得到对应的哈希值(981922613b2afb6025042ff6bd878ac1994e85),作为这个object在Git仓库中的唯一id。现在的Git仓库是这样子的,如图:

tree类型的object

接着执行下一个命令,

$ git commit -m '第一次提交'

执行git commit命令后,objects目录下又多出了两个object,如图:

首先,用git cat-file -t命令查看f4目录下object的类型,如图:

可以看到,这个object的类型是tree,利用git cat-file -p命令查看这个object的内容,如图:

可以看到,tree类型的object存储了一个目录结构的快照,从左到右分别显示了每个文件的权限、类型、object的id(SHA1值)、以及文件名。现在的Git仓库是这样子的,如图:

commit类型的object

用同样的方法,查看3c目录下的文件,如图:

这是一个commit类型的object,而这个object存储了一个tree类型的object的id,以及提交的一些信息。现在的Git仓库是这样子的,如图:

分支

实际做项目都会有很多分支,Git的分支信息就存储在/.git/refs/heads目录下,如图:

因为现在只有一个master分支,所以只有一个master文件。直接打开master这个文件,可以看到这个文件存储了3c0acd6df4df30074678a2b97967a82efd9c8acf这样一串字符串,这正是上面的commit类型object的id。现在的Git仓库是这样子的,如图:

HEAD

在/.git/HEAD这个文件下,记录内容如下:

ref: refs/heads/master

这个内容告诉Git当前修改的内容是基于哪个分支上的,我们可以理解为这是一个指针。现在的Git仓库是这样子的,如图:

至此,一个完整的Git存储结构就出来了。

Git的三个分区

Git有3个分区,分别是工作区、暂存区和版本库。

工作区: 就是项目所在目录(除去.git目录),所有代码编辑都在这上面完成。

暂存区: 英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。

Git仓库: 由Git object记录着每一次提交的快照,以及链式结构记录的提交变更历史。

有了3个分区,整个结构如下图:

Git的内部运作

现在,我们尝试修改a.txt文件,如图:

这时候,除了工作目录下的a.txt文件内容有变化,暂存区和Git仓库都是没有变化的。接着,执行git add a.txt命令,这时/.git/objects目录下又多了一个对象,如图:

这个新增的object也是blob类型,对应着新修改的a.txt文件。这时,整个结构如下图:

最后,我们执行git commit -m '修改a.txt'命令,不出意外,/.git/objects目录会生成两个object,根据上面的介绍,这两个object分别是tree和commit类型,如图:

这时,整个结构如下图:

从上图可以看到,master分支已经指向新的commit object,并且新的commit object记录着它的parent object,也就是旧的那个commit object,这使得我们可以查看Git的提交历史。

探索Git内部原理的更多相关文章

  1. Git 内部原理--初探 .git

    说到Git大家应该都非常熟悉,几乎每天都会用到它.在日常使用过程中,我们貌似并不需要关注其内部的原理,只需要记住那几个常用的命令,就可以说自己是会Git的人了.可是,事实真的是这样子的吗?今天我们就来 ...

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

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

  3. git内部原理

    Git 内部原理 无论是从之前的章节直接跳到本章,还是读完了其余章节一直到这——你都将在本章见识到 Git 的内部工作原理 和实现方式. 我们发现学习这部分内容对于理解 Git 的用途和强大至关重要. ...

  4. Git详解之九 Git内部原理

    以下内容转载自:http://www.open-open.com/lib/view/open1328070620202.html Git 内部原理 不管你是从前面的章节直接跳到了本章,还是读完了其余各 ...

  5. git内部原理-第一篇

    本人计划写一些关于<git内部原理>的文章 计划每周一篇

  6. Git 内部原理 - (7)维护与数据恢复 (8) 环境变量 (9)总结

    维护与数据恢复 有的时候,你需要对仓库进行清理 - 使它的结构变得更紧凑,或是对导入的仓库进行清理,或是恢复丢失的内容. 这个小节将会介绍这些情况中的一部分. 维护 Git 会不定时地自动运行一个叫做 ...

  7. Git内部原理(1)

    Git本质上是一套内容寻址文件系统,在此之上提供了VCS的用户界面. Git底层命令(plumbing) vs 高层命令(porcelain) Git的高层命令包括checkout.branch.re ...

  8. Git内部原理探索

    目录 前言 Git分区 .git版本库里的文件/目录是干什么的 Git是如何存储文件信息的 当我们执行git add.git commit时,Git背后做了什么 Git分支的本质是什么 HEAD引用 ...

  9. Git 内部原理 - (1)底层命令和高层命令 (2Git 对象

    文章摘选自git官网,这里复制下来表示我已阅读并学习过一次这些内容: 无论是从之前的章节直接跳到本章,还是读完了其余章节一直到这——你都将在本章见识到 Git 的内部工作原理和实现方式. 我们发现学习 ...

  10. Git内部原理浅析

    Git独特之处 Git是一个分布式版本控制系统,首先分布式意味着Git不仅仅在服务端有远程仓库,同时会在本地也保留一个完整的本地仓库(.git/文件夹),这种分布式让Git拥有下面几个特点: 1.直接 ...

随机推荐

  1. 记录一次py2编码带来的坑

    "中文" == u"中文" # PY2 False"中文" == u"中文" # PY3 True

  2. MVC和WebAPI如何从Filter向Action中传递数据

    http://www.itfanr.cc/2016/04/17/transfer-data-from-filter-to-action/ MVC和WebAPI如何从Filter向Action中传递数据 ...

  3. Spring一套全通2—工厂高级

    百知教育 - Spring系列课程 - 工厂高级特性 第十章.对象的生命周期 1. 什么是对象的生命周期 指的是一个对象创建.存活.消亡的一个完整过程 2. 为什么要学习对象的生命周期 由Spring ...

  4. CF455D Serega and Fun 题解

    题目链接:CF 或者洛谷 本题是可以用平衡树去做的,具体的为每个 \(k\) 开一棵平衡树去维护相对位置,而这种移动操作用平衡树维护又是很容易做到的,这种做法是双 \(log\).在 \(1e5\) ...

  5. [windows10]下Bad owner or permissions on .ssh/config的解决办法

    按如下步骤操作即可: 进入如下路径C:\Users\用户名.ssh,你会看到有config这个文件 右击config,属性→安全→高级→禁止继承→删除所有继承→确定 如果系统是英文: Properti ...

  6. 传统.NET应用向微服务架构迁移的实践经验--学习笔记

    摘要 在本次分享中,演讲嘉宾将基于真实项目案例,剖析 .NET 应用向微服务..NET Core 等技术栈迁移的具体收益,并且分享在迁移中技术和非技术的众多考量.以及保证业务连续性的一些方法论. 议题 ...

  7. 如何在windows端安装和配置maven

    1.下载maven 从官方下载maven,下载页面:http://maven.apache.org/download.cgi 2.安装maven maven压缩包解压到一个没有中文,空格或其他特殊字符 ...

  8. Linux-sshpass(shell脚本使用ssh远程执行命令通过密码的方式登录)

    1. sshpass简介 sshpass 是一个在非交互式 ssh 会话中自动输入密码的工具.它可以直接在命令行中指定密码,因此可以用于 Shell 脚本等自动化场景.在 Red Hat 系统中,可以 ...

  9. 优雅地使用pt-archiver进行数据归档(转)

    一.引言 最近由于业务需求,需要将公有云RDS(业务库)的大表数据归档至私有云MySQL(历史库),以缩减公有云RDS的体积和成本. 那么问题来了,数据归档的方式有n种,选择哪种呢?经过一番折腾,发现 ...

  10. maven打包更改版本号

    引入依赖 <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>versions-mave ...