2017-03-03 109 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