利用一個下午,把對Cherry Pick的一些問題整理成一篇文章,並且這個指令常常與Rebase, Merge兩者來對比,目前感覺如下
指令 | merge | rebase | cherry pick |
---|---|---|---|
說明 | 將一條分支合進另一條分支中。不會破壞提交歷史的完整性,但缺點是合併後的提交歷史較為混亂,有時可能會產生冗長的提交歷史。 | 將當前分支與目標分支結合,並以目標分支為底(base)重新出發。將一個分支中的提交歷史應用到另一個分支上,使得目標分支中的提交歷史變得更加緊湊和簡潔 | 命令可以從一個分支中選擇單個提交,並將其應用到另一個分支上,通常用於需要特定提交的情況。只想要某個分支的某些commit,不希望把整個分支搬過來 |
指令 | git merge salve | git rebase main | git cherry-pick c4 |
圖示 | |||
優點 | 簡單易操作,不破壞commit歷史 | 不產生多餘commit 與分支線 | 不會更動到Commit的歷史順序 |
缺點 | 會產生額外的分支合成線 | 不可以在共用分支上使用,否則將打斷commit順序,破壞commit完整性 | 若cherry pick commit過多,易產生重複的commit紀錄 |
應用場景 | 整合分支 | 用以取得別的分支整個進度 | 用以取得別的分支的個別進度 |
預覽
這是一個SpringBoot專案,Main分支目前長這樣,並且還有兩個協作者,分別是Hoxton跟Dallas
SourceTree如下
Hoxton這個有四個Commit
依序如下
- 創建MemberDao f198
- 創建MemberService 185a
- 創建MemberController 310a
- 為MemberController新增一個方法 99b2
- 刪除MemberController fd8b
Dallas這個分支有兩個Commit
- 創建LoginContorller 7eb2
- 為LogingController新增一個方法 e92a
Main這個分支有一個Commit
- 創建README fce6
接下來在不同情境下,使用Cherry Pick,看看會有什麼結果與問題
實際演練
Main需要hoxton的進度,其中有包含Main上未有的檔案(99b2)
結果:
發生衝突,因Main上沒有MemberController。雖然最新的Commit 只有對MemberController更新,沒有創建MemberController的部分,但因為要Cherry Pick的關係,所以還是會把MemberController創建起來,並且其內容是最新的內容至於Service、Dao則不會帶過來,因為那是屬於別的Commit的,因此最終是長這樣,綠色部分是新增的部分
hoxton-310a 創建Member Controller
hoxton-99b2 在Member Controller新增方法
Main只需要Hoxton的幾個進度,其中的commit並非連續(310a, f198)
結果:
將MemberController與Dao創建進來,其中不包含Dao,因為Cherry-pick的部分不包含,注意到的是,因為Cherry pick時我們的指令是這樣
|
|
因此Commit 的順序調換了,變成先Controller在Dao
檔案長這樣
Main只需要Hoxton的幾個進度,其中的commit並非連續(f198, 310a)
結果:
將MemberController與Dao創建進來,其中不包含Service,因為Cherry-pick的部分不包含,注意到的是,因為我們Cherry Pick的指令如下
|
|
因此Commit 順序與hoxton上分支的順序一樣
檔案長這樣
Cherry-pick一個只有刪除檔案的commit,是否能成功
fd8b這個Commit是將MemberController刪掉,在Main上cherry Pick後會發生什麼事情呢?
結果
結果:
顯示
Bad revision
直接不讓cherry-pick,我猜多半是因為這個Commit只有包含刪除,因此沒辦法pick
Cherry-pick一個範圍的commit,最終的結果呈現如何?
|
|
結果:
假設現在Dallas需要Hoxton的Commit,它合進去Main後會長什麼樣子呢?
如果兩邊合進Main之後會長怎麼樣呢?會不會兩邊都有重複的Commit導致畫面很亂呢?
結果:
會,合進去後會有許多重複的commit,因為Cherry pick過去後,雖然看起來一樣,但它們的Hash Code已經有所不同,因此會有重複的情形發生