iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 12
2
Software Development

用樂高玩轉 GIT 版本控制系列 第 12

Day 12 - 你手冊新增的部分不錯,我們合作吧!分支合體技 git merge

還記得 Day 08 的樂高案例劇情嗎?當有人將一個樂高手冊的基礎版本,分享出來,有兩個網友同時基於這個基礎版本,各自實作自己的手冊。現在 A 網友發現 B 網友延伸製作的部分很不錯,但又想要保留自己目前已經做的內容,那該怎麼做?「合併」應該是必然的解決方案,把 B 網友製作的部分,跟 A 網友製作的部分合併在一起,就可以兩個願望一次滿足了。

那 GIT 可以做分支的合併嗎?git merge

在 GIT 官方的手冊中,是這樣描述 git merge 這個指令的:

Join two or more development histories together

一、Merge 這個指令,也就是用來合併開發紀錄用的。首先,我們舉一個例子,現在基於 master 分支,我們額外建立了兩個分支,名稱分別是 apple 及 banana,在 apple 分支裡頭,有一個名為 apple.html 的檔案,同樣的在 banana 分支裡,建立了 banana.html 這個檔案。(目前兩個檔案都沒有任何內容)

案例圖說

這時候,如果我在 apple 分支,執行了 git merge banana 會發生什麼事情?首先 GIT 會詢問你要為這次的合併寫些什麼註解。

詢問合併的相關訊息

撰寫完畢後,就會發現,apple 這個分支裡,出現了 banana.html 這個檔案。

檔案清單裡出現了 banana.html

查看 GIT 的圖形也可以發現,目前在 apple 這個分支,增加了一個合併 banana 分支的紀錄。

SourceTree 的合併後線圖

那 banana 分支呢?它依然還指在原本圖片中 959748a 的那個 commit 上面,並不會因為在 apple 分支 merge 了 banana 分支,而消失。可以想像,我只是把你的手冊,和我不一樣的地方「抄過來」。

所以這時候如果透過 git checkout banana 到 banana 分支,可以發現,是沒有 apple.html 的。

不會看到 apple.html

這時候如果在 banana 分支上,持續的編輯 banana.html,並且 commit,也是可以持續的使用 banana 分支,並且 commit 後,banana 分支也會持續的往新的 commit 指向。

回到 banana 分支上編輯,banana 分支也持續的會往新 HASH 指向

二、如果是在同一個檔案上分別在不同的分支上有不一樣的編輯呢?

第一個例子中,在不同的分支,新增不一樣的兩個檔案,合併的時候,自然出現另一個分支的檔案,還算好理解,但如果是兩個分支都撰寫了同一個檔案呢?以下的例子,我們同樣有 apple 及 banana 兩個分支。

目前 SourceTree 的線圖,個別有兩個 commit

同時編輯 fruit.txt 這個檔案,在 apple 分支上,分別新增兩行文字。

在 apple 分支上 fruit.txt 的內容

同樣的在 banana 分支上,也新增兩行文字。

在 banana 分支上 fruit.txt 的內容

在 apple 分支上,執行 git merge banana 會出現什麼事情?

首先和第一個例子一樣的,同樣有一個紀錄合併的 commit 出現。

首先和第一個例子一樣的,同樣有一個紀錄合併的 commit 出現

而 fruit.txt 的內容,的確也出現的兩行 banana 分支所加入的文字。

出現的兩行 banana 分支所加入的文字

這個例子想表達什麼?所謂的 merge 如同第一個例子提到的,git merge只是把你的手冊,和我不一樣的地方「抄過來」,而抄的這個動作,就紀錄在因為合併而產生的那個 commit。

合併所產生的 commit 其實也就是 banana 和 apple 分支不一樣的地方

三、以樂高來說 Merge

如上一個例子,假設我們提供了一個底板作為基礎版本,我們叫它 master。

樂高基板

A 版本基於這個底板,分別有兩個步驟,在底板的左邊先增加了粉紅色的積木,而後增加了蘋果綠的積木。

樂高 A 版本

B 版本同樣基於底板,也同樣有兩個步驟,在右邊增加了綠色的積木,而後增加了黑色的積木。

樂高 B 版本

這時候 A 版本 Merge B 版本,其實就是把 B 版本基於「底板」不一樣的地方,在 A 版本上,再實作一次,只是會出現一個「把 B 版本的內容再實作一次」的紀錄在手冊上。

樂高合併

總結:

Merge 的概念,就像是「把別的分支和我不一樣的地方,整組抄過來一次」,只是那個抄的過程,都直接紀錄在合併的那個 commit 上了。

對於 GIT 來說,每個 commit 都是基於上一個步驟,紀錄變化,而 merge,也就是從兩個分支的共同起源開始(上面的例子就是基板),把你做的每個步驟的變化內容,在我這邊,再次的實現一次

之後開始,會提到更多 GIT 合併及重組變化的指令,因此「每個 commit 都是記錄基於上一個 commit 而做的改變」,這個概念我覺得非常的重要。


上一篇
Day 11 - 切換 branch 與 還原目前工作區檔案:git checkout, restore, switch
下一篇
Day 13 - 你的就是我的 再談 git merge
系列文
用樂高玩轉 GIT 版本控制30

尚未有邦友留言

立即登入留言