『現學現忘』Git分支 — 39、Git中分支與對象的關係

1、Git對象之間的關係

我們之前學了Git的三個對象:提交對象樹對象數據對象

我們假設現在有一個工作目錄,裏面進行了三次提交,包括一次新增文件和兩次對文件的修改。

  • 每次一把工作區中的文件添加到暫存區時,暫存操作會為每一個文件計算校驗和,然後會把當前版本的文件快照(即文件的內容)保存到 Git 倉庫中 (Git 使用 blob 對象來保存它們),最後將校驗和加入到暫存區域等待提交。
  • 每一次使用 git commit 命令進行提交操作時,Git會先計算每一個子目錄的校驗和, 然後在 Git 倉庫中這些校驗和保存為樹對象
    隨後,Git 便會創建一個提交對象, 它除了包含上面提到的那些信息外,還包含指向這個樹對象的指針。 如此一來,Git 就可以在需要的時候重現此次保存的快照。

此時的Git倉庫中就會有五個Git對象:三個 blob 對象(保存着文件快照)、一個 對象 (記錄著目錄結構和 blob 對象索引)以及一個 提交 對象(包含着指向前述樹對象的指針和所有提交信息)。

這個對象之間的關係,如下圖:

image

總結提交對象樹對象數據對象之間的關係:

  1. 一個提交操作生成一個提交對象。
  2. 一個提交對象包含一個(暫存區)生成Tree對象。(對Tree對象的封裝,單方向一對一)
  3. 一個(暫存區)生成Tree對象,裏面包含子Tree對象和Blob對象。子Tree對象還可以繼續包含子Tree對象和Blob對象。
    這樣子Tree對象對應文件系統中的目錄+文件名Blob對象對應着文件中的內容,這就是Git中數據存儲的形式。
  4. 一個Blob對象對應着一個文件某一時刻的版本。

三種對象之間的關係如下圖:

image

那麼問題來了:每一個Commit對象,是怎樣的組合到一起的呢?

2、提交對象與分支的關係

(1)提交對象與分支的關係

Git版本管理系統是以時間線來對版本進行管理的,這條時間線上會有很多的時間節點,這些時間節點就是一個個的Commit對象。

即:Git的每次提交,都會自動把它們串成一條時間線,這條時間線就是一個分支。

如下圖所示:每一次提交產生的提交對象,會包含一個指向上次提交對象(父對象)的指針,這樣就形成了一條鏈狀結構,就相當於一條線。

image

(2)分支說明

Git的分支,其實本質上僅僅是指向提交對象的可變指針。

Git倉庫初始化之後,會默認創建一個master分支,即主分支。

如果沒有新建分支,那麼就只有一條時間線,即只有一個分支,master分支(主分支)。

每次提交操作之後,會生成新的提交對象(如上圖), master 分支會在每次提交時自動向前移動。(也就是自動指向最新的提交對象)

(3)HEAD與分支的關係

我們在學習Git的時候,常常會看到HEAD這個名稱,它指的是什麼呢?

Git中維護一個名為HEAD的引用變量,我們將此變量稱為指針,它的目的是引用或指向本地版本庫中的特定提交。

當我們進行新的提交時,指針將改變或移動,以指向新的提交。

HEAD始終指向Git本地版本庫中當前正在工作的分支的尖端(即最新一次提交)。

概括來說:HEAD是對當前分支中,最後一次提交的引用。(可以將HEAD想像為是,當前分支最後一次提交的別名。)

再繼續:

HEAD嚴格來說不是指向提交,而是指向master(分支),master(分支)才是指向具體的提交,所以,HEAD指向的就相當於是當前分支的最新一次提交。

如下圖所示:

image

Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點。

(當然HEAD還有一種分離的狀態,我們以後單說,關於HEAD就先理解到這裡就很詳細了)