【學了就忘】Git操作 — 60.charry-pick命令詳解

對於多分支的代碼庫,將代碼從一個分支轉移到另一個分支是常見需求。

這時分兩種情況:

  • 一種情況是,你需要另一個分支所有代碼的變動,那麼就採用合併(git merge)。
  • 另一種情況是,你只需要另一個分支的部分代碼變動(某一個或幾個提交),這時可以採用git cherry-pick

1、cherry-pick命令介紹

git cherry-pick命令可以理解爲"挑揀"提交,它會獲取某一分支中的一個或者多個提交,並作爲一個新的提交(或新的多個提交),引入到你當前的工作分支上。

也就是當我們需要在本地合併其他分支的提交時,如果我們不想對整個分支進行合併,而是隻想將某一次提交合併到本地當前分支上,那麼就要使用git cherry-pick了。

git cherry-pick命令說明:

git cherry-pick [<options>] <commit-ish>...

常用options:
    --quit                退出當前的chery-pick序列
    --continue            繼續當前的chery-pick序列
    --abort               取消當前的chery-pick序列,恢復當前分支
    -n, --no-commit       不自動提交
    -e, --edit            編輯提交信息

2、cherry-pick命令基本用法

git cherry-pick命令的作用,就是將指定的提交(commit)應用於其他分支。

$ git cherry-pick <commitHash>

上面命令就會將指定的提交commitHash,應用於當前分支。這會在當前分支產生一個新的提交,當然它們的哈希值會不一樣。

舉例來說,代碼倉庫有masterfeature兩個分支。

    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分支的最近一次提交,轉移到當前分支上。

如下:

    a - b - c - d - g   Master
         \
           e - f - g    Feature

我們可以通過插圖來觀察:

cherry-pick操作前:

cherry-pick操作後:

我們可以看到a0a41cherry-pick操作新生成的新提交,且形成了一個三方合併,會容易產生衝突。

3、轉移多個提交

cherry-pick操作支持一次轉移多個提交。

$ git cherry-pick <HashA> <HashB>

上面的命令將 A 和 B 兩個提交應用到當前分支。這會在當前分支生成兩個對應的新提交。

如果想要轉移一系列的連續提交,可以使用下面的簡便語法。

$ git cherry-pick A..B 

上面的命令可以轉移從 A 到 B 的所有提交。

它們必須按照正確的順序放置:提交 A 必須早於提交 B,否則命令將失敗,但不會報錯。

注意,使用上面的命令,提交 A 將不會包含在git cherry-pick選擇的提交中。如果要包含提交 A,可以使用下面的語法。

$ git cherry-pick A^..B 

4、其他用法

把另一個分支中沒有的提交,合併到當前工作分支。

使用命令:git cherry-pick ..< branchname > 或者 git cherry-pick ^HEAD < branchname >

以上兩個命令作用相同,表示把一個分支中獨有的提交合併到另一個分支上,共有的提交不進行合併。

假設:現在我的倉庫中有三個分支,其提交歷史如下:

               C<---D<---E  branch2
              /
master   A<---B  
              \
               F<---G<---H  branch3
                         |
                         HEAD

如果我使用 git cherry-pick ..branch2 命令或者 git cherry-pick ^HEAD branch2 命令,那麼會將屬於branch2分支的祖先,但不屬於branch3分支的祖先的所有提交,都引入到當前分支branch3上,並生成新的提交。

執行命令後的提交歷史如下:

               C<---D<---E  branch2
              /
master   A<---B  
              \
               F<---G<---H<---C<---D<---E  branch3
                                        |
                                       HEAD

5、配置選項說明

git cherry-pick命令的常用配置項如下。

  • (1)-e,--edit:打開外部編輯器,編輯提交信息。
  • (2)-n,--no-commit:只更新工作區和暫存區,不產生新的提交。
  • (3)-x:在提交信息的末尾追加一行(cherry picked from commit ...),方便以後查到這個提交是如何產生的。
  • (4)-s,--signoff:在提交信息的末尾追加一行操作者的簽名,表示是誰進行了這個操作。
  • (5)-m parent-number,--mainline parent-number:如果原始提交是一個合併節點,來自於兩個分支的合併,那麼git cherry-pick命令默認將執行失敗,因爲它不知道應該採用哪個分支的代碼變動。
    -m配置項告訴 Git,應該採用哪個分支的變動。它的參數parent-number是一個從1開始的整數,代表原始提交的父分支編號。
    示例:$ git cherry-pick -m 1 <commitHash>
    上面命令表示,git cherry-pick命令採用提交commitHash來自編號1的父分支的變動。
    一般來說,1號父分支是接受變動的分支(the branch being merged into),2號父分支是作爲變動來源的分支(the branch being merged from)。

6、代碼衝突

如果操作過程中發生代碼衝突,git cherry-pick命令會停下來,讓用戶決定如何繼續操作。

(1)--continue

用戶解決代碼衝突後,第一步將修改的文件重新加入暫存區(git add .),第二步使用下面的命令,讓git cherry-pick命令過程繼續執行。

$ git cherry-pick --continue

(2)--abort

發生代碼衝突後,放棄合併,回到操作前的樣子。

(3)--quit

發生代碼衝突後,退出git cherry-pick命令,但是不回到操作前的樣子。

7、轉移到另一個代碼庫

git cherry-pick命令也支持轉移另一個代碼庫的提交,方法是先將該庫加爲遠程倉庫。

# 添加了一個遠程倉庫`target`。
$ git remote add target git://gitUrl

然後,將遠程代碼抓取到本地。

# 將遠程代碼倉庫抓取到本地。
$ git fetch target

接着,檢查一下要從遠程倉庫轉移的提交,獲取它的哈希值。

$ git log target/master

target/master是本地的遠程跟蹤分支(以後會說明)。

最後,使用git cherry-pick命令轉移提交到當前工作分支。

$ git cherry-pick <commitHash>

8、常見問題

(1)問題1

The previous cherry-pick is now empty, possibly due to conflict resolution.:先前的cherry-pick操作爲空,可能是由於解決衝突所致。

原因:在執行git cherry-pick命令時出現衝突,解決衝突後,本地分支中內容和cherry-pick操作之前相比沒有改變。因此在以後的操作中,繼續git cherry-pick命令或執行其他命令時,由於此時還處於上次cherry-pick狀態,都會提示該信息,表示可能是由於解決衝突造成上一次cherry-pick操作的內容是空的。

解決方案:

  1. 執行git cherry-pick --abort命令,取消上次cherry-pick操作。
  2. 執行git commit --allow-empty命令,表示允許空提交。

(2)問題2

fatal: You are in the middle of a cherry-pick – cannot amend.:致命:您處於cherry-pick操作中,無法修改。

原因:在cherry-pick操作時出現衝突,沒有解決衝突就執行git commit --amend命令,從而會提示該信息。

解決方案:

  1. 首先在執行git commit --amend命令之前,先解決衝突。
  2. 完成這次cherry-pick操作:
    $ git add .
    $ git cherry-pick --continue

參考:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章