git 在cherry-pick工作后git如何合并?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14486122/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does git merge after cherry-pick work?
提问by Paul
Let's imagine that we have a master
branch.
假设我们有一个master
分支。
Then we create a newbranch
然后我们创建一个 newbranch
git checkout -b newbranch
and make two new commits to newbranch
: commit1and commit2
并进行两次新的提交newbranch
:commit1和commit2
Then we switch to master and make cherry-pick
然后我们切换到 master 并 make cherry-pick
git checkout master
git cherry-pick hash_of_commit1
Looking into gitk
we see that commit1and its cherry-picked version have different hashes, so technically they are two different commits.
查看gitk
我们发现commit1及其精选版本具有不同的哈希值,因此从技术上讲,它们是两个不同的提交。
Finally we merge newbranch
into master
:
最后我们合并newbranch
为master
:
git merge newbranch
and see that these two commits with different hashes were merged without problems although they imply that the same changes should be applied twice, so one of them should fail.
并看到这两个具有不同散列的提交合并没有问题,尽管它们意味着相同的更改应该应用两次,因此其中一个应该失败。
Does git really do a smart analysis of commit's content while merging and decide that changes shouldn't be applied twice or these commits are marked internally as linked together?
git 是否真的在合并时对提交的内容进行了智能分析,并决定不应两次应用更改,或者这些提交在内部标记为链接在一起?
采纳答案by helmbert
Short answer
简答
Don't worry, Git will handle it.
别担心,Git 会处理的。
Long answer
长答案
Unlike e.g. SVN1, Git does not store commits in delta format, but is snapshot-based2,3. While SVN would naively try to apply each merged commit as a patch (and fail, for the exact reason you described), Git is generally able to handle this scenario.
与 SVN 1不同,Git 不以增量格式存储提交,而是基于快照的2,3。虽然 SVN 会天真地尝试将每个合并的提交作为补丁应用(并且由于您描述的确切原因而失败),但 Git 通常能够处理这种情况。
When merging, Git will try to combine the snapshots of both HEAD commits into a new snapshot. If a portion of code or a file is identical in both snapshots (i.e. because a commit was already cherry-picked), Git won't touch it.
合并时,Git 会尝试将两个 HEAD 提交的快照合并为一个新快照。如果部分代码或文件在两个快照中是相同的(即因为提交已经被挑选出来),Git 将不会触及它。
Sources
来源
回答by ephemerr
After such merge you may have cherry-picked commits in history twice.
在这样的合并之后,你可能在历史上有两次精选的提交。
Solution to prevent this I quote from articlewhich recommends for branches with duplicate(cherry-picked) commits use rebase before merge:
防止这种情况的解决方案我从文章中引用,该文章建议具有重复(樱桃挑选)提交的分支在合并之前使用 rebase:
git merge after git cherry-pick: avoiding duplicate commits
Imagine we have the master branch and a branch b:
o---X <-- master \ b1---b2---b3---b4 <-- b
Now we urgently need the commits b1 and b3 in master, but not the remaining commits in b. So what we do is checkout the master branch and cherry-pick commits b1 and b3:
$ git checkout master $ git cherry-pick "b1's SHA" $ git cherry-pick "b3's SHA"
The result would be:
o---X---b1'---b3' <-- master \ b1---b2---b3---b4 <-- b
Let's say we do another commit on master and we get:
o---X---b1'---b3'---Y <-- master \ b1---b2---b3---b4 <-- b
If we would now merge branch b into master:
$ git merge b
We would get the following:
o---X---b1'---b3'---Y--- M <-- master \ / b1----b2----b3----b4 <-- b
That means the changes introduced by b1 and b3 would appear twice in the history. To avoid that we can rebase instead of merge:
$ git rebase master b
Which would yield:
o---X---b1'---b3'---Y <-- master \ b2'---b4' <-- b
Finally:
$ git checkout master $ git merge b
gives us:
o---X---b1'---b3'---Y---b2'---b4' <-- master, b
git cherry-pick 后的 git 合并:避免重复提交
假设我们有一个 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
EDITCorrections supposed by David Lemon's comment
编辑David Lemon 的评论所认为的更正