git cherry-pick 與 git show + git apply 與 git merge

如果是有部分的更改或新增功能,用 git merge 有時候不見得是好主意

git merge的好處是可以直接把某 branch commit 直接整合入另一 branch,但如果 conflict 超多,有時候反而 resolve conflict 會搞到瘋掉,特別是兩個 branch 已經分道揚鑣很久。

另一個情況是,某個 commit 的”一部分”修改,要套用在現在的 branch 上,那 merge 也是不太適用。這時候 git cherry-pick 就很適合,特別是加上 -n (i.e. –no-commit) 這個指令會把另個 commit 的修改全部 apply 過來,例如;

$ git cherry-pick 951c5c77 -n
$ git status
On branch A
Your branch is up to date with 'origin/A'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

  modified:   js/main.js
  modified:   main.html

cherry-pick不需要的部分可以用git rest 配合 git add來完成。

另一種方式是用 git show 配合 git apply,前者可以顯示某個 commit 做的變更,如果加上檔案名稱,就只列出該檔案的變更。例如:

$ git show 951c5c77 main.html
commit 951c5c77be28f0a8c3f21f406895aab187003473 (origin/A, A)
Author: P <p@test.com>
Date:   Thu Mar 28 14:58:43 2019 +0800

    some commit message

diff --git a/main.html b/main.html
index 8f5c4ac..c4f97f3 100644
--- a/main.html
+++ b/main.html
@@ -84,11 +84,11 @@
                                <div class="carousel-inner" role="listbox">
                                        
                                </div>
-                               <a class="left carousel-control" href="#glasses-selection" role="button" data-slide="prev">
+                               <a class="left carousel-control" href="#glasses-selection" role="button" data-slide="prev" id="preitems">
                                        <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
                                        <span class="sr-only">Previous</span>
                                </a>
-                               <a class="right carousel-control" href="#glasses-selection" role="button" data-slide="next">
+                               <a class="right carousel-control" href="#glasses-selection" role="button" data-slide="next" id="nextitems">
                                        <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
                                        <span class="sr-only">Next</span>
                                </a>

列出不一樣的部分,然後再 git apply 就可以更新過去了。

$ git show 951c5c77 main.html | git apply

不過用 cherry-pick 或 git show + git apply 都不會有類似 git merge 的那種 commit relation 被建立就是,可能得靠 commit message 才能知道關聯性。