挑选工作后,git如何合并?

假设我们有一个master分支。

然后我们创build一个新的newbranch

 git checkout -b newbranch 

并提交两个新的提交到新newbranchcommit1commit2

然后我们切换到主人并cherry-pick

 git checkout master git cherry-pick hash_of_commit1 

看着gitk我们看到commit1和它的cherry-pick版本有不同的哈希,所以在技术上它们是两个不同的提交。

最后我们把newbranch合并到master

 git merge newbranch 

并且看到这两个不同哈希的提交没有问题合并,尽pipe它们暗示着同样的修改应该应用两次,所以其中一个应该失败。

git是否真的在合并的时候对提交的内容做了一个明智的分析,并决定不应该改变两次,或者这些提交被内部标记为链接在一起?

简短的回答

别担心,Git会处理它。

长答案

不像例如SVN 1 ,Git不以delta格式存储提交,而是基于快照 2,3 。 虽然SVN会天真地尝试将每个合并的提交作为补丁应用(并且出于您描述的确切原因而失败),但Git通常能够处理这种情况。

合并时,Git将尝试将两个HEAD提交的快照合并到一个新的快照中。 如果代码或文件的一部分在两个快照中是相同的(即,因为提交已经被挑选出来),Git将不会触及它。

来源

1 Subversion中的Skip-Deltas
2个 Git基础
3 Git对象模型

合并之后,你可能会有两次历史上的挑剔的承诺。

解决scheme,以防止这个我引用文章 ,build议分支与重复(樱桃采摘)提交使用rebase之前合并:

git樱桃挑选后git merge:避免重复的提交

想象一下,我们有主分支和一个分支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