commit時Git都幹了些啥?--- 提交對象

本文首發於公衆號「AntDream」,歡迎微信搜索「AntDream」或掃描文章底部二維碼關注,和我一塊兒天天進步一點點git

提交對象

通常咱們平時有了須要提交的文件,都是2步走:add,而後commit數據庫

add操做

第一步:添加文件bash

//添加文件到暫存區
git add test.txt
複製代碼

這一步Git作了2件事:微信

  • 將文件的內容用以前數據對象一節中提到的方法建立數據對象並保存到Git數據庫中(計算SHA-1值、生成文件目錄、寫入壓縮後的內容)
  • 更新 Index文件,也就是咱們平時說的 暫存區,增長或是更新指向text.txt 文件的索引,等待後續的第二步操做
commit:建立提交記錄
//提交到Git本地倉庫
git commit -m "XXX"
複製代碼

這個步驟是建立了一個提交對象,提交對象裏面就記錄了提交的時間、做者、以及提交的緣由等信息。ui

上述 git commit 命令作了如下幾件事:spa

  • 首先全部具體文件的數據,已經在 add 操做時用數據對象記錄在Git數據庫中,而且全部文件的索引都保存在暫存區中,因此 commit 操做就不用再建立數據對象了code

  • 若是暫存區中存在目錄關係,就會先建立樹對象來記錄文件目錄關係,這樣文件數據和目錄關係都有了記錄cdn

  • 而後會再建立一個樹對象,表明當前項目快照,這個樹對象裏面包含的就是上述信息,也就是全部要保存記錄的數據對象

  • 而後用這個樹對象,配置中的user.name和email,以及當前的時間戳和 -m 參數後面的內容生成提交對象blog

咱們能夠用 git log 命令,查看提交的歷史記錄,就能拿到 commit 的 SHA-1值(也就是咱們平時說的commit id)

而後用 git cat-file 命令就能查看這個提交裏面的信息

git cat-file -p xxxxxxx0ab25ce7b1c6019c411e760a17205d7b0
//輸出
tree 9bfb857f532d280ecd7704beb40a2ea4ba332f5a
author xxx <xxx@qq.com> 1561964726 +0800
committer xxx <xxx@qq.com> 1561964726 +0800

first commit
複製代碼

能夠看到,commit 裏面確實是有一個樹的索引,這個樹對象就是前面建立的頂層樹對象。

此時,有個疑問:已經用暫存區的內容建立了提交對象,那暫存區的內容還在嗎?

答案是:仍然存在

Git在執行commit命令時會根據暫存區建立樹對象,暫存區沒變,建立的樹對象就是同一個,也就是不會重複建立。

最後咱們看看commit對象的一個示意圖

commit歷史記錄

上面咱們用 git commit 命令建立了一個commit對象,實際上底層調用的是 commit-tree 命令。

commit-tree 命令裏面須要肯定2個參數:一個是須要指定一個樹對象,第二個須要指定上一個提交對象(做爲父提交對象)

// -p 後面的就是上一個提交對象
echo 'second commit' | git commit-tree 0155eb -p fdf4fc3
複製代碼

下面咱們來模擬連續提交3次

echo 'version 1' > test.txt
git add .
git write-tree
//輸出樹對象SHA-1值
d8329fc1cc938780ffdd9f94e0d364e0ea74f579

//建立第一個提交對象
echo 'first commit' | git commit-tree d8329fc
//輸出提交對象的SHA-1值
xxxxxxxc670d30e9817fd1af481aca92f8d700c2

//而後添加新文件,建立新的樹對象
echo 'version 2' > test.txt 
echo 'new file' > new.txt
git add .
git write-tree 
//輸出新的樹對象的SHA-1值
0155eb4229851634a0f03eb265b69f5a2d56f341

//接着建立新的提交對象
echo 'second commit' | git commit-tree 0155eb -p 9f17fcc
//輸出新提交對象的SHA-1值
xxxxxxx9f57c7a0632084e2c9eb38e3584180e23


//先把以前的初版的test.txt讀入暫存區做爲子樹
git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579
git write-tree
//輸出新樹的SHA-1值
3c4e9cd789d88d8d89c1073707c3585e41b0e614

//接着建立新的提交對象
echo 'third commit' | git commit-tree 3c4e9c -p 8565637
//輸出第3次提交的SHA-1值
xxxxxxx747d9e83f3c05d10cbc68f876a8abf0d1
複製代碼

以上咱們用 git的底層命令模擬了實際的三次 git commit操做,咱們來看一下成果:

//--stat參數可讓git顯示每一次提交改動的文件信息
git log --stat f32da7d
複製代碼

經過以上的步驟咱們就從底層知道了咱們每次 git addgit commit 的過程,同時咱們知道,每一次咱們 commit 的時候,都會記錄上一個 commit 的 SHA-1值,這樣一個個的 commit 就串起了咱們的提交記錄。

那麼問題來了,Git是怎麼知道新 commit 對象的上一個 commit 對象的呢?實際上就是上面commit-tree 命令中的第二個參數---父提交對象,每一個提交對象都保存了上一個父提交對象的引用,這樣就串起來一個提交歷史記錄了。


歡迎關注個人公衆號查看更多精彩文章!
複製代碼

AntDream
相關文章
相關標籤/搜索