2017-03-03 113 views
7

我有兩個分支:ABgit cherry-pick不只是挑選提交的差異

  • A的提交歷史:a <- b <- c;
  • B的提交歷史:a <- h <- i;

假設這裏只有一個文件。

  1. 在提交b中,我添加了一些文本,如「foo」。
  2. 在提交c,我添加了一些文本,如「酒吧」。
  3. 然後我git cherry-pick cB分支。我認爲cherry-pick只會選擇c到分支B的更改。但是,它會將foobar添加到分支B。這顯然不是我想要的。

因此,cherry-pick會挑選那些文件的所有變化觸動了提交c因爲祖先犯下a。是對的嗎?如果我只想從b挑選差異至c並將其應用於i

更新的確切步驟

  1. 初始化一個git回購;
  2. 添加文件test.txt併發出第一次提交init committest.txt現在是:

    first line 
    second line 
    
  3. 創建一個新的分支dev但留在分支master;

  4. added in commit b添加到文件併發出提交btest.txt現在是:

    first line 
    added in commit b 
    second line 
    
  5. 添加added in commit c該文件併發出commit ctest.txt現在是:

    first line 
    added in commit b 
    added in commit c 
    second line 
    
  6. 退房dev分支發出commit htest.txt現在是:

    first line 
    second line 
    
    adding by commit h 
    
  7. git cherry-pick <commit c SHA1 ID>來摘櫻桃提交c到提交h

  8. 衝突消息:

    index 6a8dc57,594c6ec..0000000 
    @@@ -1,4 -1,4 +1,9 @@@ 
        first line 
    ++<<<<<<< HEAD 
    ++======= 
    + added in commit b 
    + added in commit c 
    ++>>>>>>> 06ce9b1... commit c adding another line 
        second line 
    + 
    +adding by commit h 
    
  9. 看到了嗎?cherry-pick也帶來了改變b

謝謝!

+0

這可能會幫助你的http: //stackoverflow.com/questions/9339429/what-does-cherry-picking-a-commit-with-git-mean –

+0

@ArunG謝謝!我知道「櫻桃挑」是什麼意思。但我只是困惑,它不等於獲取該提交的差異並將diff應用於目標分支。它還包含該提交中的內容** NOT **。 – tamlok

+0

@tamlok,運行'git show a'(顯然用相關提交SHA替換'a')來檢查提交實際會引入的更改,以瞭解爲什麼您可能會從提交'b'獲得增量。您始終可以使用'-n'標誌運行'cherry-pick'來停止並手動修剪不需要的更改。 – miqid

回答

4

git cherry-pick試圖只提交一個提交。但它通過應用需要一些上下文的補丁來實現。在提交C中完成的更改與提交b完成的更改非常接近,因此您會遇到衝突 - 它無法找到必須應用更改的正確位置。而當你有衝突,你也得到了一些相互矛盾的情況下,它至少你犯B.

這裏怎麼會沒有衝突工作的一部分:

$ git init 
$ cat > f 
line1 
line2 
line3 
$ git add f 
$ git commit -a -m "initial" 
# Edited to add a line in the beginning of f 
$ cat f 
Commit b 
line1 
line2 
line3 
$ git commit f -m "B" 
# Edited to add a line in the end of f 
$ cat f 
Commit b 
line1 
line2 
line3 
Commit c 
$ git commit f -m "C" 
$ git checkout HEAD^^ 
$ git cherry-pick master 
$ cat f 
line1 
line2 
line3 
Commit c 
+0

那麼'git cherry-pick master'會選擇提交'c'而不是'b'和'c'?那是當'git cherry-pick'使用分支名稱時,它只會選擇最後一次提交?謝謝! – tamlok

+0

我剛剛嘗試過'git cherry-pick master'。結果是一樣的,衝突內容仍然包含提交'b'中的更改。 :( – tamlok

+0

明白了!謝謝! – tamlok

0

如果我只想從b到c挑選差異並將其應用於i,該怎麼辦?

您可以在兩次提交(c..d)之間找到/寫入文件的diff。然後將其應用於當前分支。

$ git checkout <B-branch> 

# write the diff in a file named 'change.patch' (root directory) 
$ git diff <b-commit> <c-commit> <file-name> >> ~/changes.patch 

$ git apply ~/changes.patch  # apply the changes 
$ git add . 

# merge the changes to i (previous commit) 
$ git commit --amend -m 'Apply the diff of b and c' 

$ git push -f origin HEAD  # force(-f) push since history is changed 
+0

我知道這種「原始」的方式。但是根據git cherry-pick的描述,爲什麼它還會從其他未指定的提交中選擇額外的更改?謝謝! – tamlok

+0

在我的情況下,補丁並沒有完全適用,所以我必須使用' - 3way'選項進行三路合併。然後,我得到了與使用'git cherry-pick'完全相同的結果,除了錯誤被靜音,並且似乎回到沒有擡頭的三種方式。我仍然不明白爲什麼三條合併會導致這一結果,但我的兩個分支已經分化很多,所以可能是相關的。 – angularsen