17

鉴于两个分支已经分歧,并且需要将来自一个分支(而不是所有内容)的特定提交引入另一个分支, git cherry pick 正是实现了这一点。

一段时间后,需要将两个分支完全合并。git 如何知道它已经拥有过去挑选的提交,这样它就不会重新引入它?

4

2 回答 2

30

tonio 的回答中提到的“避免重复提交”文章说:

假设我们有 master 分支和一个分支 b:

  o---X   <-- master
   \
    b1---b2---b3---b4   <-- b

现在我们迫切需要 master 中的 b1 和 b3 提交,而不是 b 中剩余的提交。所以我们要做的是检查 master 分支并选择提交 b1 和 b3:

$ git checkout master
$ git cherry-pick “b1’s SHA”
$ git cherry-pick “b3’s SHA”

结果将是:

  o---X---b1'---b3'   <-- master
   \
    b1---b2---b3---b4   <-- b

假设我们在 master 上再次提交,我们得到:

  o---X---b1'---b3'---Y   <-- master
   \
    b1---b2---b3---b4   <-- b

如果我们现在将分支 b 合并到 master 中:

$ git merge b

我们会得到以下信息:

  o---X---b1'---b3'---Y--- M  <-- master
   \                     /
     b1----b2----b3----b4   <-- b

这意味着 b1 和 b3 引入的更改将在历史记录中出现两次。为了避免这种情况,我们可以变基而不是合并:

$ git rebase master b

这将产生:

  o---X---b1'---b3'---Y   <-- master
                       \
                        b2---b4   <-- b

最后:

$ git checkout master
$ git merge b

给我们:

  o---X---b1'---b3'---Y---b2---b4   <-- master, b

(在这个线程之后)


OP在评论中添加:

但似乎我还是不太明白变基是如何工作的。我的意思是即使在变基之后,樱桃挑选的提交也不应该出现吗?

不,git commit手册页明确提到:

如果上游分支已经包含您所做的更改(例如,因为您邮寄了一个应用于上游的补丁),那么该提交将被跳过
例如,在以下历史记录上运行 git rebase master(其中 A' 和 A 引入了相同的更改集,但具有不同的提交者信息):

      A---B---C topic
     /
D---E---A'---F master

将导致:

               B'---C' topic
              /
D---E---A'---F master

您可以检测 master 上是否已经存在提交git cherry master(如果您在topic分支上)。

于 2010-04-13T10:54:38.247 回答
16

您可能想阅读

Git Cherry-pick vs Merge Workflow在合并和cherry-pick之间进行了很好的比较,特别是cherry-pick不存储父ID,因此不会知道它已经拥有过去被挑选的提交,因此它不会重新介绍它。

http://davitenio.wordpress.com/2008/09/27/git-merge-after-git-cherry-pick-avoiding-duplicate-commits/关于如何避免在这种情况下重复提交,使用rebase.

于 2010-04-13T08:33:28.213 回答