假设我们有一个 master
分支。
然后我们创建一个 newbranch
git checkout -b newbranch
并对 newbranch
进行两次新的提交:commit1 和 commit2
然后我们切换到master并制作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 Skip-Deltas in Subversion
2 Git Basics
3 The Git object model
在这样的合并之后,您可能会在历史上两次精选提交。
防止这种情况的解决方案我引用了 article,它建议具有重复(樱桃采摘)提交的分支在合并之前使用 rebase:
git cherry-pick 之后的 git merge:避免重复提交假设我们有 master 分支和一个分支 b:o---X <-- master \ b1---b2---b3---b4 <-- b 现在我们迫切需要 master 中的提交 b1 和 b3,而不是 b 中的剩余提交。所以我们要做的是检查 master 分支和 cherry-pick 提交 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 引入的更改将在历史记录中出现两次。为了避免这种情况,我们可以 rebase 而不是合并: $ 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
编辑大卫柠檬的评论所提出的更正
---Y---b2'---b4'
不定期副业成功案例分享