『现学现忘』Git对象 — 17、Commit对象
1、Commit对象介绍
现在来介绍最后一种Git对象commit
对象,也叫提交对象。
提交对象可以理解为是对树对象的一层封装,提交信息包括基于当前暂存区中索引文件生成的tree
对象,还有包含了提交时间,提交者信息,作者信息,以及提交备注等内容,更重要的是里面还包含了父提交的ID,由此就可以形成Git提交的有向无环图。(是链式的关系,把所有commit
对象关联起来)
即:commit
对象通常指向一个 tree
对象,并且封装了文件的提交时间,提交者信息,作者信息,提交备注,以及父提交引用等数据。
下面是commit
对象的存储结构:
2、Commit对象说明
我们通过练习来说明commit
对象,接着用前面Tree
对象的本地版本库。
(1)创建一个commit
对象
我们可以通过调用commit-tree
命令创建一个提交对象,为此需要指定一个树对象的SHA-1
值,以及该提交的父提交对象。
说明:使用
commit-tree
命令来创建提交对象,一般都需要和父提交进行关联,如果是第一次将暂存区的文件索引数据提交到本地版本库,那么该提交操作就不需要指定父提交对象。
1)我们可以先查看一下此时Git本地库中的对象,如下:
.git/objects/01/ab2a43b1eb150bcf00f375800727df240cf653 # 第三个tree树对象
.git/objects/0c/1e7391ca4e59584f8b773ecdbbb9467eba1547 # test.txt第二个版本(blob对象)
.git/objects/16/3b45f0a0925b0655da232ea8a4188ccec615f5 # 第二个tree树对象
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30 # test.txt第一个版本(blob对象)
.git/objects/d8/329fc1cc938780ffdd9f94e0d364e0ea74f579 # 第一个tree树对象
.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt第一个版本(blob对象)
2)我们通过第一个树对象,创建一个commit
对象
# 1.做提交操作,创建一个commit对象
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/git_learning (master)
$ echo 'first commit' | git commit-tree d8329f
3ceba95d3cd9cce982d31e41e3b995ece72f755d
# 2.确定该对象类型
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/git_learning (master)
$ git cat-file -t 3ceba95d3c
commit
# 3.查看该对象内容
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/git_learning (master)
$ git cat-file -p 3ceba95d3c
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author sun_wk <sun_wk@126.com> 1618190880 +0800
committer sun_wk <sun_wk@126.com> 1618190880 +0800
first commit
说明:
tree
:表示该commit
对象所指向的tree
对象的索引author
:表示该文件的作者。committer
:表示该文件的提交者。first commit
:这段文本是提交备注。(备注与前面留空一行)- 因为是第一次进行
commit
提交操作,所以没有父提交信息。 1618190880 +0800
:表示时间,一个时间戳。
即:
commit
对象的格式很简单:指明了该时间点项目快照的顶层树对象、作者/提交者信息(从 Git 设置的user.name
和user.email
中获得),以及当前时间戳、留空一行,最后是提交注释。
提示:
git commit-tree
命令不但生成了提交对象,而且会将对应的快照(树对象)提交到本地库中。
(2)创建第二个commit
对象
根据第二个tree
对象和第一个commit
对象,来创建第二个commit
对象。
通过-p
选项指定父提交对象。
# 1.创建第二个commit对象
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/git_learning (master)
$ echo 'second commit' | git commit-tree 163b45f0a09 -p 3ceba95d3cd9cc
60e1c209e9de87314ec47cf28e61de8df5362fe6
# 2.查看该对象内容
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/git_learning (master)
$ git cat-file -p 60e1c209e9de8
tree 163b45f0a0925b0655da232ea8a4188ccec615f5
parent 3ceba95d3cd9cce982d31e41e3b995ece72f755d
author sun_wk <sun_wk@126.com> 1618193286 +0800
committer sun_wk <sun_wk@126.com> 1618193286 +0800
second commit
提交对象的格式很简单:
它先指定一个顶层树对象,代表当前项目快照;
然后是可能存在的父提交;
之后是作者/提交者信息(依据你的
user.name
和user.email
配置来设定,外加一个时间戳);留空一行,最后是提交注释。
第三个commit
提交,同上,这里就不演示了。
3、本地库中对象之间的关系
我们可以查看一下此时Git本地库中的对象
.git/objects/01/ab2a43b1eb150bcf00f375800727df240cf653 # 第三个tree树对象
.git/objects/0c/1e7391ca4e59584f8b773ecdbbb9467eba1547 # test.txt第二个版本(blob对象)
.git/objects/16/3b45f0a0925b0655da232ea8a4188ccec615f5 # 第二个tree树对象
.git/objects/3c/eba95d3cd9cce982d31e41e3b995ece72f755d # 第一个commit提交对象
.git/objects/46/ab608799a0e65e970b67b9b52f6c1407c39036 # 第三个commit提交对象
.git/objects/60/e1c209e9de87314ec47cf28e61de8df5362fe6 # 第二个commit提交对象
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30 # test.txt第一个版本(blob对象)
.git/objects/d8/329fc1cc938780ffdd9f94e0d364e0ea74f579 # 第一个tree树对象
.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt第一个版本(blob对象)
可以从上面看到,此时的本地版本库中共有9个对象,三个blob
对象,三个tree
对象,三个commit
对象。
他们之间的关系如下图:
4、总结
- 提交是我们经常使用的Git动作,每次提交操作都指向一个树对象,同时会产生一个
commit
对象。
即:一个commit
对象包含了一个tree
对象,这个tree
对象记录了在那个时间点,项目包含了什么文件夹和什么文件。 - 一个提交对象可以有一个或者多个父提交。
- 每次
commit
操作都会基于当前索引文件index新建tree
对象。那么当前索引文件,是在上次提交的基础上更新来的,所以每次提交产生的commit
对象,与其他的commit
对象,都有前后关系或者称为父子关系。 - 对于我们来说,不需要直接访问
blob
对象和tree
对象,我们直接访问commit
对象就可以了。
即:commit
对象对应的tree
对象下面,又包含了小的tree
对象和blob
对象,子的tree
对象一层层展开,最后叶子节点就是一个个blob
对象,也就是一个个文件。
到这里,我们就能够清楚的了解,什么叫一个Git版本。
tree
对象才是一次项目版本的快照,提交对象是对tree
对象的一次封装。即:
- 项目的快照就是一个树对象。
- 项目的版本就是一个提交对象。
而且Git的每一个版本,存储的不是增量,而存储的是当前项目的快照。同时
objects
目录中相当于存放了项目的所有历史记录,回滚就相当的方便了,找到对应的commit
对象的hash就可以了。
5、练习
请问下图中包含多少个tree
对象和blob
对象?
一共包含两个tree
对象,一个blob
对象,一个commit
对象。
说明:
- 一个
commit
对象一定对应一个tree
对象(这个tree
对象应该是一个完整项目仓库的快照) doc
目录下有一个blob
对象,也就是readme
文件。
6、本文用到的命令总结
Git底层命令:
git commit-tree
:生成一个commit
对象。git cat-file -t 键
:查看Git对象的类型。git cat-file -p 键
:查看Git对象的内容。
参考:
『现学现忘』Git对象 — 17、Commit对象的更多相关文章
- 『现学现忘』Git基础 — 18、Git对象的总结
目录 1.Git操作最基本的流程 2.工作目录中文件的状态 3.Git效率说明 提示:前面三篇文章已经分别的对blob对象.tree对象.commit对象进行了详细的说明,这篇文章我们总结一下,Git ...
- 『现学现忘』Git对象 — 16、Tree对象详解
目录 1.Tree对象介绍 2.Tree对象说明 (1)初始化一个新的本地版本库 (2)创建一个树对象(重点) (3)创建第二个文件(重点) (4)将第一个树对象加入暂存区,使其成为新的树对 3.总结 ...
- 『现学现忘』Git分支 — 39、Git中分支与对象的关系
目录 1.Git对象之间的关系 2.提交对象与分支的关系 (1)提交对象与分支的关系 (2)分支说明 (3)HEAD与分支的关系 1.Git对象之间的关系 我们之前学了Git的三个对象:提交对象.树对 ...
- 『现学现忘』Git对象 — 15、blob对象介绍
目录 (一)Git对象的存放目录 (二)Git中对象类型 (三)blob对象 1.blob对象说明 (1)blob对象定义 (2)blob对象说明 (3)blob对象存储的方式 (4)查看blob对象 ...
- 『现学现忘』Git基础 — 5、Git的协作模式
目录 1.分布式工作流程 2.集中式工作流 3.分支工作流 4.GitFlow 工作流(最流行) 5.Forking 工作流(偶尔使用) 6.总结 1.分布式工作流程 与传统的集中式版本控制系统(CV ...
- 『现学现忘』Git基础 — 36、标签tag(一)
目录 1.标签介绍 2.列出标签 3.创建标签 (1)标签的分类 (2)附注标签 (3)轻量标签 4.后期打标签 1.标签介绍 软件的某个发行版本所对应的,其实就是软件开发过程中,某一个阶段的最后一次 ...
- 『现学现忘』Git基础 — 37、标签tag(二)
目录 5.共享标签 6.删除标签 7.修改标签指定提交的代码 8.标签在.git目录中的位置 9.本文中所使用到的命令 提示:接上一篇文章内容. 5.共享标签 默认情况下,git push 命令并不会 ...
- 『现学现忘』Git基础 — 24、Git中查看历史版本记录
目录 1.查看详细的历史版本记录 2.简化显示历史版本记录 3.历史版本记录常用操作 (1)指定查看最近几次提交的内容 (2)以简单图形的方式查看分支版本历史 (3)翻页与退出 4.查看分支相关的版本 ...
- 『现学现忘』Git后悔药 — 33、revert撤销(二)
目录 4.一次移除某几次提交 (1)git revert移除某几次提交的修改 (2)git revert 移除某几次连续的提交的修改 5.revert命令常用参数 6.git revert和git r ...
随机推荐
- 什么是openssl?
在计算机网络上,OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份.这个包广泛被应用在互联网的网页服务器上.
- Kafka 都有哪些特点?
高吞吐量.低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作. ...
- 说一下 jvm 有哪些垃圾回收器?
新生代收集器: SerialParNewParallel Scavenge 老年代收集器: Serial OldCMSParallel Old 堆内存垃圾收集器: G1 参考链接:JVM常见的垃圾回收 ...
- Linux 环境下如何查找哪个线程使用 CPU 最长?
1.获取项目的 pid,jps 或者 ps -ef | grep java,这个前面有讲过 2.top -H -p pid,顺序不能改变
- C语言之main方法解析(知识点1)
1.注释 /*自带注释*/2.引包 #include <stdio.h>3.主方法 void main{}4.执行体 printf("打印& ...
- (stm32学习总结)—对寄存器的理解 _
芯片里面有什么 我们看到的 STM32 芯片是已经封装好的成品,主要由内核和片上外设组成.若与电脑类比,内核与外设就如同电脑上的 CPU 与主板.内存.显卡.硬盘的关系.STM32F103 采用的是 ...
- -> 在c语言中是什么意思?
->在C语言中称为间接引用运算符,是二目运算符,优先级同成员运算符".".用法:p->a,其中p是指向一个结构体的指针,a是这个结构体类型的一个成员.表达式p-> ...
- Rust 中的数据布局--可选的数据布局
Rust 允许你指定不同于默认的数据布局策略,并为你提供了不安全代码指南. repr(C) 这是最重要的"repr".它的意图相当简单:做 C 所做的事.字段的顺序.大小和对齐方式 ...
- C++函数声明的时候后面加const
非静态成员函数后面加const(加到非成员函数或静态成员后面会产生编译错误),表示成员函数隐含传入的this指针为const指针,决定了在该成员函数中,任意修改该类中成员的操作都是不允许的(因为隐含了 ...
- stm32 中库函数、结构体、地址的强制类型转换、相应特殊功能寄存器之间的关系
以一个挂接在APB2上的外设函数使能为例 A : RCC_APB2PeriphClockCmd():时钟使能函数 1 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFI ...