2010-11-08 52 views
9

在閱讀git cherry-pick的手冊頁時,我的理解是它只需要一次提交引入的更改,然後可以在任何地方應用這些更改。我誤解git cherry-pick?

所以我們可以說我有我建立了4個提交像這樣一個文件:

line from commit 1 
line from commit 2 
line from commit 3 
line from commit 4 

如果我再開始另一個分支在提交1,我應該能夠得到

line from commit 1 
line from commit 4 

櫻桃採摘4

如果我有這個權利,那爲什麼它不起作用?我遇到了衝突,然後當我看到衝突時,看起來好像git試圖從提交2,3,4中提取行。這是我的工作日誌(跳到這裏的肉看肉..):

szbwood-mbp15:proj5 bwood$ git init 
Initialized empty Git repository in /Users/bwood/work/gitplay/proj5/.git/ 
szbwood-mbp15:proj5 bwood$ vi file1 
szbwood-mbp15:proj5 bwood$ git add file1 
szbwood-mbp15:proj5 bwood$ git commit -a 
[master (root-commit) 4cb9b97] .. 
1 files changed, 1 insertions(+), 0 deletions(-) 
create mode 100644 file1 
szbwood-mbp15:proj5 bwood$ vi file1 
szbwood-mbp15:proj5 bwood$ git commit -a 
[master 809d87c] .. 
1 files changed, 1 insertions(+), 0 deletions(-) 
szbwood-mbp15:proj5 bwood$ vi file1 
szbwood-mbp15:proj5 bwood$ git commit -a 
[master b534ac9] .. 
1 files changed, 1 insertions(+), 0 deletions(-) 
szbwood-mbp15:proj5 bwood$ vi file1 
szbwood-mbp15:proj5 bwood$ git commit -a 
[master fabc779] .. 
1 files changed, 1 insertions(+), 0 deletions(-) 
szbwood-mbp15:proj5 bwood$ git log 
commit fabc7795fb660d55a7ad5636321b6180157954f7 
Author: B 
Date: Sun Nov 7 21:58:07 2010 -0800 

    .. 

commit b534ac9d1f8139fc7ffa9479a3d0cb0fd08c9508 
Author: B 
Date: Sun Nov 7 21:57:53 2010 -0800 

    .. 

commit 809d87c24b1c2d27354d6bfcb34d3a1981cb7ae5 
Author: B 
Date: Sun Nov 7 21:57:35 2010 -0800 

    .. 

commit 4cb9b97c3cae9b9551fa039f87e2fff5624fbbe3 
Author: B 
Date: Sun Nov 7 21:57:19 2010 -0800 

    .. 
szbwood-mbp15:proj5 bwood$ git checkout 4cb9b97c3cae9b9551fa039f87e2fff5624fbbe3 
Note: checking out '4cb9b97c3cae9b9551fa039f87e2fff5624fbbe3'. 

You are in 'detached HEAD' state. You can look around, make experimental 
changes and commit them, and you can discard any commits you make in this 
state without impacting any branches by performing another checkout. 

If you want to create a new branch to retain commits you create, you may 
do so (now or later) by using -b with the checkout command again. Example: 

    git checkout -b new_branch_name 

HEAD is now at 4cb9b97... .. 
szbwood-mbp15:proj5 bwood$ git checkout -b new_branch 
Switched to a new branch 'new_branch' 

這裏的肉

szbwood-mbp15:proj5 bwood$ more file1 
line from commit 1 
szbwood-mbp15:proj5 bwood$ git cherry-pick -x fabc7795fb660d55a7ad5636321b6180157954f7 
Automatic cherry-pick failed. After resolving the conflicts, 
mark the corrected paths with 'git add <paths>' or 'git rm <paths>' 
and commit the result with: 

     git commit -c fabc7795fb660d55a7ad5636321b6180157954f7 

szbwood-mbp15:proj5 bwood$ more file1 
line from commit 1 
<<<<<<< HEAD 
======= 
line from commit 2 
line from commit 3 
line from commit 4 
>>>>>>> fabc779... .. 
szbwood-mbp15:proj5 bwood$ 
+0

爲什麼我會發生衝突?即使我在第2次提交時啓動新分支,我也會發生衝突 - 爲什麼在文件末尾添加一行會給我一個衝突?我認爲有些東西我錯過了,但我不知道它是什麼 - 或者我不會錯過它。 – bruce 2010-11-08 06:14:30

回答

17

這裏的問題不在於Git的實際試圖到插入內容從提交2和3,它是從提交4的內容交織着,從提交2和3。承諾4補丁看起來是這樣的:

line from commit 1 
line from commit 2 
line from commit 3 
+line from commit 4 

(除非考慮到這看起來像一個測試用例,我猜你可能在那裏沒有任何行)。

因此,當git試圖將該補丁應用於提交1中的文件內容時,它表示,嗯,我需要在第3行後面插入這一行。呃哦,那不是。好的,文件中的那一行在哪裏?它反向工作並設法將其匹配起來,但知道有些東西是可疑的 - 它必須添加不是修補程序的一部分才能使修補程序適用的行。這裏的關鍵思想是通過匹配邊緣來應用補丁 - 補丁不只是說「添加到文件的末尾」,它說「在這條內容之後添加」。

所以它給了你一個衝突:HEAD(提交1)中的版本在這個位置沒有任何東西,並且提交4中的版本有這三行。這取決於你決定這兩行是否是最後一行的「一部分」,並且需要引入插入才能理解,或者它們是否與它分離,並且可以被刪除。這與正常合併衝突中您將看到的完全相同。

如果您在補丁不相交的示例中嘗試此操作 - 提交2和3將更改與提交4中的任何內容進行了幾行更改,或者更好,與提交4中的不同文件相比 - 您會看到您的行爲期待從櫻桃挑選。你完全正確地理解了這個目的;你只是有一個凌亂的測試用例。

+0

啊非常感謝你的清楚,有益的答案。是的,我誤解了這些補丁是如何應用的 - 我認爲它只是將該行添加到「文件末尾」。我不知道如何通過邊緣進行匹配 - 我猜這是必要算法的一部分,因爲確定如何進行修補並不簡單?我改變了我的測試用例,以便我的初始文件包含第1-3行,而第4行的櫻桃選擇非常整潔地沒有衝突。再次感謝:-) – bruce 2010-11-08 06:28:00

+0

@bruce:我也不知道細節;重要的部分是要應用補丁,上下文必須匹配。 – Cascabel 2010-11-08 06:37:26