『現學現忘』Git對象 — 17、Commit對象
- 2022 年 4 月 27 日
- 筆記
- 高級測試技能 - Git基礎
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 <[email protected]> 1618190880 +0800
committer sun_wk <[email protected]> 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 <[email protected]> 1618193286 +0800
committer sun_wk <[email protected]> 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對象的內容。
參考: