1. 程式人生 > >git merge原理

git merge原理

快照


這是專案的三個版本,版本1中有兩個檔案A和B,然後修改了A,變成了A1,形成了版本2,接著又修改了B變為B1,形成了版本3。

如果我們把專案的每個版本都儲存到本地倉庫,需要儲存至少6個檔案,而實際上,只有4個不同的檔案,A、A1、B、B1。為了節省儲存的空間,我們要像一個方法將同樣的檔案只需要儲存一份。這就引入了Sha-1演算法。

可以使用git命令計算檔案的 sha-1 值。

echo 'test content' | git hash-object --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4

SHA-1將檔案中的內容通過通過計算生成一個 40 位長度的hash值。

Sha-1的非常有特點:

  • 由檔案內容計算出的hash值
  • hash值相同,檔案內容相同

對於上圖中的內容,無論我們執行多少次,都會得到相同的結果。因此,檔案的sha-1值是可以作為檔案的唯一 id 。同時,它還有一個額外的功能,校驗檔案完整性。

有了 sha-1 的幫助,我們可以對專案版本的儲存方式做一下調整。


Conflicts

git 中的分支十分輕量,因此我們在使用git的時候會頻繁的用到分支。不可不免的需要將新建立的分支合併。

在 git 中合併分支有兩種選擇:merge 和 rebase。但是,無論哪一種,都有可能產生衝突。因此我們先來看一下衝突的產生。


圖上的情況,並不是移動分支指標就能解決問題的,它需要一種合併策略。首先,我們需要明確的是誰和誰的合併,是 2,3 與 4,5,6的合併嗎?說到分支,我們總會聯想到線,就會認為是線的合併。其實不是的,真實合併的是 3 和 6。因為每一次提交都包含了專案完整的快照,即合併只是 tree 與 tree 的合併。

我們可以先想一個簡單的演算法。用來比較3和6。但是我們還需要一個比較的標準,如果只是3和6比較,那麼3與6相比,添加了一個檔案,也可以說成是6與3比刪除了一個檔案,這無法確切表示當前的衝突狀態。因此我們選取他們的兩個分支的分歧點(merge base)作為參考點,進行比較。

比較時,相對於 merge base(提交1)進行比較。

首先把1、3、6中所有的檔案做一個列表,然後依次遍歷這個列表中的檔案。現在我們拿列表中的一個檔案進行舉例,把在提交1、3、6中的該檔案分別稱為版本1、版本3、版本6。

  1. 版本1、版本3、版本6的 sha-1 值完全相同,這種情況表明沒有衝突
  2. 版本3或6至少一個與版本1狀態相同(指的是sha-1值相同或都不存在),這種情況可以自動合併。比如1中存在一個檔案,在3中沒有對該檔案進行修改,而6中刪除了這個檔案,則以6為準就可以了
  3. 版本3或版本6都與版本1的狀態不同,情況複雜一些,自動合併策略很難生效,需要手動解決。我們來看一下這種狀態的定義。