對於多分支的代碼庫,將代碼從一個分支轉移到另一個分支是常見需求。
這時分兩種情況。一種情況是,你需要另一個分支的所有代碼變動,那么就采用合並(git merge
)。另一種情況是,你只需要部分代碼變動(某幾個提交),這時可以采用 git cherry-pick。
git merge的操作對象是branch,而git cherry-pick的操作對象是commit。
一、基本用法
git cherry-pick
命令的作用,就是將指定的提交(commit)應用於其他分支。
$ git cherry-pick <commitHash>
上面命令就會將指定的提交commitHash
,應用於當前分支。這會在當前分支產生一個新的提交,當然它們的哈希值會不一樣。
舉例來說,代碼倉庫有master
和feature
兩個分支。
a - b - c - d Master \ e - f - g Feature
現在將提交f
應用到master
分支。
# 切換到 master 分支 $ git checkout master # Cherry pick 操作 $ git cherry-pick f
上面的操作完成以后,代碼庫就變成了下面的樣子。
a - b - c - d - f Master \ e - f - g Feature
從上面可以看到,master
分支的末尾增加了一個提交f
。
git cherry-pick
命令的參數,不一定是提交的哈希值,分支名也是可以的,表示轉移該分支的最新提交。
$ git cherry-pick feature
上面代碼表示將feature
分支的最近一次提交,轉移到當前分支。
二、轉移多個提交
Cherry pick 支持一次轉移多個提交。
$ git cherry-pick <HashA> <HashB>
上面的命令將 A 和 B 兩個提交應用到當前分支。這會在當前分支生成兩個對應的新提交。
如果想要轉移一系列的連續提交,可以使用下面的簡便語法。
$ git cherry-pick A..B
上面的命令可以轉移從 A 到 B 的所有提交。它們必須按照正確的順序放置:提交 A 必須早於提交 B,否則命令將失敗,但不會報錯。
注意,使用上面的命令,區間是左閉右開的,即提交 A 將不會包含在 Cherry pick 中。如果要包含提交 A,可以使用下面的語法。
$ git cherry-pick A^..B
三、配置項
git cherry-pick
命令的常用配置項如下。
(1)-e
,--edit
打開外部編輯器,編輯提交信息。
(2)-n
,--no-commit
因為cherry-pick命令轉移多個提交時每揀選一個commit就會提交一次生成一個新的commit id。 如果我們想讓每個commit 揀選后暫緩提交,等到所有commit都揀選完成后,自己手動commit,應該怎么辦呢?答案是用-n 選項:只更新工作區和暫存區,不產生新的提交。
(3)-x
在提交信息的末尾追加一行(cherry picked from commit ...)
,方便以后查到這個提交是如何產生的。
(4)-s
,--signoff
在提交信息的末尾追加一行操作者的簽名,表示是誰進行了這個操作。
(5)-m parent-number
,--mainline parent-number
如果原始提交(commitHash所在提交)是一個合並節點,來自於兩個分支的合並,那么 Cherry pick 默認將失敗,因為它不知道應該采用哪個分支的代碼變動。
-m
配置項告訴 Git,應該采用哪個分支的變動。它的參數parent-number
是一個從1
開始的整數,代表原始提交的父分支編號。
$ git cherry-pick -m 1 <commitHash>
上面命令表示,Cherry pick 采用提交commitHash
來自編號1的父分支的變動。
一般來說,1號父分支是接受變動的分支(the branch being merged into),2號父分支是作為變動來源的分支(the branch being merged from)。
四、代碼沖突
如果操作過程中發生代碼沖突,Cherry pick 會停下來,讓用戶決定如何繼續操作。
(1)--continue
用戶解決代碼沖突后,第一步將修改的文件重新加入暫存區(git add .
),第二步使用下面的命令,讓 Cherry pick 過程繼續執行。
$ git cherry-pick --continue
(2)--abort
發生代碼沖突后,放棄合並,回到操作前的樣子。
(3)--quit
發生代碼沖突后,退出 Cherry pick,但是不回到操作前的樣子。