樱桃选择问题:也会应用以前提交的更改

时间:2017-03-01 11:22:21

标签: git cherry-pick git-cherry-pick

在我的项目中,我几个月前发布了一个版本。在那个版本之后,我在master分支上做了很多更改。

如果我在最后一个版本中遇到一些错误,我会在主分支上修复它们,然后将它们挑选到我在上一版本中创建的分支。然后我可以提供一个只有bug修复的新版本,而不会在master分支上发布未完成的工作。

当我尝试向发布分支挑选某个错误修复时,我遇到了合并冲突。

据我了解,cherry选择某个提交会向目标分支引入一个新提交,并在提取的提交中完成更改。

但是,当我尝试修复合并冲突时,似乎git已经在master分支上应用了更改,这些更改不是由我选择的提交提交给我的发布分支。樱桃选择提交只引入了冲突文件的几行。但是,当我尝试解决冲突时,我看到该文件中还引入了其他几行,这些行被添加到具有不同提交的主分支中。

有人可以解释为什么我的发布分支会引入除了樱桃挑选提交之外的提交更改吗?

2 个答案:

答案 0 :(得分:8)

  

据我了解,cherry选择某个提交会向目标分支引入一个新提交,并在提取的提交中完成更改。

这是正确的。但是,这些更改可能不适用,在这种情况下:

  

......我遇到了合并冲突。

此时,git cherry-pick正在进行三向合并,这需要选择合并基础

我记得,哪些文件或提交用作合并基础部分取决于您的Git版本。现代Git,如果你运行git cherry-pick,则使用樱桃挑选的提交parent作为merge base,但至少使用一个表单(使用git amgit apply --3way选项,git rebase仍可以执行此选项,可以使用indexgit diff输出选择文件的早期版本。最后,这可能不应该太重要。

在任何情况下,合并实际上都会从基本提交运行git diff到两个“提示”(樱桃挑选的提交,以及您尝试应用的HEAD提交)中的每一个樱桃挑选)。要在视觉上看到正在发生的事情,您应该像往常一样从绘制提交图开始。 (我没有你的存储库,所以我会绘制一个不同的图表并希望它足够接近。但是你应该自己绘制 - 或者让Git这样做,或者使用gitk或一些这样的。)

          o--@         <-- branch (HEAD)
         /
...--o--o
         \
          I--P--C--o   <-- otherbranch

我在这里给出了各种提交的单字母名称:C是我们即将挑选的提交,P是其父级。我在这里将当前(HEAD)提交标记为@,尽管所有实际工作都将在索引和工作树中进行。 (幸运的是git cherry-pick要求索引和工作树是“干净的”,除非你使用-n将多个樱桃组装成一个大的选择,所以索引和工作树将匹配commit {{无论如何。)并且,我将提交@标记为“重要”。

现在,考虑如果我们以I作为基础进行三向合并,P作为提交之一,C作为另一个提交,会发生什么。当我们计算将@更改为P的说明时,我们会得到我们想要应用的差异:这非常简单。但是,当我们计算将C更改为P的说明时,嗯,

我们在@中做了一些重要的更改。这些更改是I的一部分,即它们位于我们的合并基础中。但是P中的不是。合并的含义是,Git会将这些重要的变化视为我们试图 un -do的事情。事实上,他们是!我们没有挑选@本身,因此我们必须撤消这些I更改,以便应用I中的更改。

如果那些C更改,我们“撤消”不在I开头,而不会影响@的任何更改,我们很好:他们已经没有了。如果,出于某种机会或目的,其中C更改中的一个 I(可能通过@的父级),那些甚至不在我们首先试图撤消的集合,所以我们再次没事。当这些更改发生冲突,或者甚至只是(上下文相关),@ - 至 - P更改时,我们有问题。

在这种情况下,Git将在两个合并冲突区域之一中显示一些C更改。这些都是我们试图挑选的部分。它们不一定被应用,它们只是我们必须解决的冲突的一部分。如果您将I设置为merge.conflictStyle - 我通常建议 - diff3更改将显示为合并基础的一部分,因为合并基础提交I,它本身基于P(即I的快照包含来自P的代码,除非我们在制作I时更改了代码

所以,我并不完全清楚你在问什么,但是 正常,在合并冲突区域看到与你正在挑选的位无关的变化。

答案 1 :(得分:1)

  

我看到该文件中还引入了其他几行,这些行已添加到具有不同提交的master分支

确保您没有对该提交进行不受欢迎的更改。

$ git show <commit-sha>

Cherry-选择提交。

$ git checkout <release-branch>
$ git cherry-pick <commit-sha>

更好地手动解决冲突。

或者,如果您想保留提交的更改,请接受theirs,否则接受ours(保持发布分支更改)

$ git checkout --theirs -- .
Or,
$ git checkout --ours -- .

$ git status                     # see the changes
$ git add .
$ git commit -m 'Fix conflicts'
$ git push origin HEAD

替代方法:如果您希望从目标提交到发布分支进行少量文件更改,此解决方案将会有效。

  

Cherry挑选的提交仅向冲突的文件引入了几行

$ git checkout <release-branch>
$ git checkout <commit-sha> <file> .      # change the <file> to commit's version

$ git add .
$ git commit -m 'Fix the bug'
$ git push origin HEAD