【學(xué)了就忘】Git原理 — 21.Git對象[commit對象]

1、Commit對象介紹

現(xiàn)在來介紹最后一種Git對象commit對象,也叫提交對象。

提交對象可以理解為是對樹對象的一層封裝,提交信息包括基于當(dāng)前暫存區(qū)中索引文件生成的tree對象,還有包含了提交時間,提交者信息,作者信息,以及提交備注等內(nèi)容,更重要的是里面還包含了父提交的ID,由此就可以形成Git提交的有向無環(huán)圖。(是鏈?zhǔn)降年P(guān)系,把所有commit對象關(guān)聯(lián)起來)

即:commit對象通常指向一個 tree 對象,并且封裝了文件的提交時間,提交者信息,作者信息,提交備注,以及父提交引用等數(shù)據(jù)。

下面是commit對象的存儲結(jié)構(gòu)

2、Commit對象說明

我們通過練習(xí)來說明commit對象,接著用前面Tree對象的本地版本庫。

(1)創(chuàng)建一個commit對象

我們可以通過調(diào)用commit-tree命令創(chuàng)建一個提交對象,為此需要指定一個樹對象的SHA-1值,以及該提交的父提交對象。

說明:使用commit-tree命令來創(chuàng)建提交對象,一般都需要和父提交進(jìn)行關(guān)聯(lián),如果是第一次將暫存區(qū)的文件索引數(shù)據(jù)提交到本地版本庫,那么該提交操作就不需要指定父提交對象。

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)我們通過第一個樹對象,創(chuàng)建一個commit對象

# 1.做提交操作,創(chuàng)建一個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.查看該對象內(nèi)容
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:這段文本是提交備注。(備注與前面留空一行)

  • 因為是第一次進(jìn)行commit提交操作,所以沒有父提交信息。

  • 1618190880 +0800:表示時間,一個時間戳。

即:commit對象的格式很簡單:指明了該時間點項目快照的頂層樹對象、作者/提交者信息(從 Git 設(shè)置的 user.nameuser.email中獲得),以及當(dāng)前時間戳、留空一行,最后是提交注釋。

提示:git commit-tree命令不但生成了提交對象,而且會將對應(yīng)的快照(樹對象)提交到本地庫中。

(2)創(chuàng)建第二個commit對象

根據(jù)第二個tree對象和第一個commit對象,來創(chuàng)建第二個commit對象。

通過-p選項指定父提交對象。

# 1.創(chuàng)建第二個commit對象
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/git_learning (master)
$ echo 'second commit' | git commit-tree 163b45f0a09 -p 3ceba95d3cd9cc
60e1c209e9de87314ec47cf28e61de8df5362fe6

# 2.查看該對象內(nèi)容
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

提交對象的格式很簡單:

它先指定一個頂層樹對象,代表當(dāng)前項目快照;

然后是可能存在的父提交;

之后是作者/提交者信息(依據(jù)你的 user.nameuser.email 配置來設(shè)定,外加一個時間戳);

留空一行,最后是提交注釋。

第三個commit提交,同上,這里就不演示了。

3、本地庫中對象之間的關(guān)系

我們可以查看一下此時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對象。

他們之間的關(guān)系如下圖:

4、總結(jié)

  1. 提交是我們經(jīng)常使用的Git動作,每次提交操作都指向一個樹對象,同時會產(chǎn)生一個commit對象。

    即:一個commit對象包含了一個tree對象,這個tree對象記錄了在那個時間點,項目包含了什么文件夾和什么文件。

  2. 一個提交對象可以有一個或者多個父提交。

  3. 每次commit操作都會基于當(dāng)前索引文件index新建tree對象。那么當(dāng)前索引文件,是在上次提交的基礎(chǔ)上更新來的,所以每次提交產(chǎn)生的commit對象,與其他的commit對象,都有前后關(guān)系或者稱為父子關(guān)系。

  4. 對于我們來說,不需要直接訪問blob對象和tree對象,我們直接訪問commit對象就可以了。

    即:commit對象對應(yīng)的tree對象下面,又包含了小的tree對象和blob對象,子的tree對象一層層展開,最后葉子節(jié)點就是一個個blob對象,也就是一個個文件。

到這里,我們就能夠清楚的了解,什么叫一個Git版本。tree對象才是一次項目版本的快照,提交對象是對tree對象的一次封裝。

即:

  • 項目的快照就是一個樹對象。
  • 項目的版本就是一個提交對象。

而且Git的每一個版本,存儲的不是增量,而存儲的是當(dāng)前項目的快照。同時objects目錄中相當(dāng)于存放了項目的所有歷史記錄,回滾就相當(dāng)?shù)姆奖懔耍业綄?yīng)的commit對象的hash就可以了。

5、練習(xí)

請問下圖中包含多少個tree對象和blob對象?


一共包含兩個tree對象,一個blob對象,一個commit對象。

說明:

  • 一個commit對象一定對應(yīng)一個tree對象(這個tree對象應(yīng)該是一個完整項目倉庫的快照)
  • doc目錄下有一個blob對象,也就是redme文件。

6、本文用到的命令總結(jié)

Git底層命令:

  • git commit-tree:生成一個commit對象。

  • git cat-file -t 鍵:查看Git對象的類型。

  • git cat-file -p 鍵:查看Git對象的內(nèi)容。

參考:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容