假设我们有一个master
分支。
然后我们创建一个newbranch
git checkout -b newbranch
并对newbranch
进行两个新的提交:commit1 和 commit2
然后我们切换到母版并制作cherry-pick
git checkout master
git cherry-pick hash_of_commit1
查看gitk
,我们看到 commit1 及其精心挑选的版本具有不同的哈希值,因此从技术上讲它们是两个不同的提交。
最后我们将newbranch
合并为master
:
git merge newbranch
并看到这两个具有不同哈希的提交被合并没有问题,尽管它们暗示相同的更改应该应用两次,因此其中一个应该失败。
git 是否真的在合并时对提交的内容进行了智能分析,并决定不应应用两次更改或这些提交在内部标记为链接在一起?
简答
别担心,Git 会处理它。
长答案
与SVN1不同,Git不以增量格式存储提交,而是基于快照的2,3。虽然SVN会天真地尝试将每个合并的提交作为补丁应用(并且由于您描述的确切原因而失败),但Git通常能够处理这种情况。
合并时,Git 将尝试将两个 HEAD 提交的快照合并到一个新快照中。如果代码或文件的一部分在两个快照中都相同(即因为提交已经精心挑选),Git 不会碰它。
来源
1 颠覆
中的跳跃三角洲2 Git 基础知识
3 Git 对象模型
在这样的合并之后,你可能会在历史上挑选两次提交。
防止这种情况的解决方案,我引用了文章,该文章建议具有重复(挑选)提交的分支在合并前使用变基:
git 挑选后的 git 合并:避免重复提交
假设我们有主分支和一个分支 b:
o---X <-- master b1---b2---b3---b4 <-- b
现在我们迫切需要在 master 中提交 b1 和 b3,但不是 B 中的剩余提交。所以我们要做的是签出主分支 樱桃拣选提交 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
假设我们在主服务器上做另一个提交,我们得到:
o---X---b1'---b3'---Y <-- master b1---b2---b3---b4 <-- b
如果我们现在将分支 b 合并到主节点中:
$ 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
编辑大卫·莱蒙的评论所假设的更正