cherry pick 问题:还应用了以前提交的更改
Issue with cherry pick: changes from previous commits are also applied
在我的项目中,几个月前发布了一个版本。在那次发布后,我在 master 分支上做了很多更改。
如果我遇到上一个版本中存在的一些错误,我会在 master 分支上修复它们,然后将它们挑选到我在上一个版本中创建的分支。然后我可以提供一个只修复错误的新版本,而不发布 master 分支上未完成的工作。
当我尝试对发布分支进行 cherry pick 某个错误修复时,遇到了合并冲突。
据我了解,cherry picking 某个提交会向目标分支引入新的提交,并在 cherry picked 提交中完成更改。
但是,当我试图解决合并冲突时,似乎 git 已经在 master 分支上应用了更改,这些更改不是由 cherry picked 提交引入到我的发布分支的。 cherry picked 提交仅向冲突文件引入了几行。但是,当我尝试解决冲突时,我看到文件中还引入了其他几行,这些行已添加到具有不同提交的 master 分支。
有人可以解释为什么将来自 cherry picked 提交以外的提交的更改引入我的发布分支吗?
I see that several other lines are also introduced to the file, which were added to master branch with different commits
确保您在该提交上没有不需要的更改。
$ git show <commit-sha>
樱桃挑选提交。
$ 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
备选方案:如果您想从目标提交到发布分支进行少量文件更改,此解决方案将很有效。
The cherry picked commit only introduced couple of lines to the conflicted file
$ 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
As I understand, cherry picking a certain commit introduces a new commit to the target branch, with the changes done in the cherry picked commit.
没错。但是,这些更改可能无法完全应用,在这种情况下:
... I encountered a merge conflict.
此时git cherry-pick
正在做三向合并,需要选择一个合并基。
哪些文件或提交被用作合并基础,部分取决于您的 Git 版本,我记得。现代 Git,如果你 运行 git cherry-pick
,使用精心挑选的提交的 parent as the merge base,但至少使用一种形式(使用 git am
或 git apply
使用 --3way
选项,git rebase
仍然可以)可以使用 git diff
输出的 index
行挑选出文件的更早版本。说到底,这应该没什么大不了的。
在任何情况下,合并实际上都会 运行 git diff
从基本提交到两个 "tips" (精心挑选的提交和 HEAD提交您尝试应用樱桃选择的内容)。要直观地查看发生了什么,您应该像往常一样从绘制提交图开始。 (我没有你的存储库,所以我会画一个 different 图,希望它足够接近。但是你应该自己画——或者让 Git 画,或者使用 gitk
或类似的东西。)
o--@ <-- branch (HEAD)
/
...--o--o
\
I--P--C--o <-- otherbranch
我在这里为各种提交提供了单字母名称:C
是我们要挑选的提交,P
是它的父提交。我在这里将我们当前的 (HEAD) 提交标记为 @
,尽管所有实际工作都将在索引和工作树中进行。 (幸运的是 git cherry-pick
要求索引和工作树为 "clean",除非您使用 -n
将多个樱桃 assemble 合并为一个大采摘,因此索引和工作-树将匹配提交 @
无论如何。)而且,我将提交 I
标记为 "important".
现在,考虑如果我们以 P
作为基础,C
作为一个提交,@
作为另一个提交进行三向合并会发生什么。当我们计算将 P
更改为 C
的指令时,我们得到了我们想要应用的差异:这非常简单。但是当我们计算将 P
更改为 @
的指令时,嗯,嗯。
我们在 I
中进行了一些重要更改。这些更改是 P
的一部分,即它们在我们的合并基础中。但在 @
中它们是 而不是 。合并的含义是 Git 会将这些重要更改视为我们正在尝试 un-做的事情。事实上,他们是!我们没有挑选 I
本身,因此我们必须撤消这些 I
更改以应用来自 C
.
的更改
无论那些 I
变化我们 "undoing" 不在 @
以 和 开始不影响任何来自 C
的更改,我们很好:它们已经撤消。如果,由于某种机会或目的,其中一个 I
改变 是 @
中的 (可能通过 @
的父级),那么这些都不是即使在 set 中,我们首先尝试撤消,所以我们再次很好。当这些变化 与 冲突,甚至只是 与 (的上下文)冲突时,P
-to-C
变化,我们有问题。
在这种情况下,Git 将在两个合并冲突区域之一中显示一些 I
更改。这些是我们试图挑选的部分。它们不一定被应用,它们只是我们必须解决的冲突的一部分。如果您将 merge.conflictStyle
设置为 diff3
——这是我通常推荐的——I
更改将显示为合并基础的一部分,因为合并基础 是 提交 P
,它本身基于 I
(即,P
的快照包括来自 I
的代码,除了我们在制作 [=22] 时更改它的地方=]).
所以,我不完全清楚你在问什么,但 正常看到,在合并冲突区域,更改与你正在处理的位无关-采摘。
在我的项目中,几个月前发布了一个版本。在那次发布后,我在 master 分支上做了很多更改。
如果我遇到上一个版本中存在的一些错误,我会在 master 分支上修复它们,然后将它们挑选到我在上一个版本中创建的分支。然后我可以提供一个只修复错误的新版本,而不发布 master 分支上未完成的工作。
当我尝试对发布分支进行 cherry pick 某个错误修复时,遇到了合并冲突。
据我了解,cherry picking 某个提交会向目标分支引入新的提交,并在 cherry picked 提交中完成更改。
但是,当我试图解决合并冲突时,似乎 git 已经在 master 分支上应用了更改,这些更改不是由 cherry picked 提交引入到我的发布分支的。 cherry picked 提交仅向冲突文件引入了几行。但是,当我尝试解决冲突时,我看到文件中还引入了其他几行,这些行已添加到具有不同提交的 master 分支。
有人可以解释为什么将来自 cherry picked 提交以外的提交的更改引入我的发布分支吗?
I see that several other lines are also introduced to the file, which were added to master branch with different commits
确保您在该提交上没有不需要的更改。
$ git show <commit-sha>
樱桃挑选提交。
$ 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
备选方案:如果您想从目标提交到发布分支进行少量文件更改,此解决方案将很有效。
The cherry picked commit only introduced couple of lines to the conflicted file
$ 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
As I understand, cherry picking a certain commit introduces a new commit to the target branch, with the changes done in the cherry picked commit.
没错。但是,这些更改可能无法完全应用,在这种情况下:
... I encountered a merge conflict.
此时git cherry-pick
正在做三向合并,需要选择一个合并基。
哪些文件或提交被用作合并基础,部分取决于您的 Git 版本,我记得。现代 Git,如果你 运行 git cherry-pick
,使用精心挑选的提交的 parent as the merge base,但至少使用一种形式(使用 git am
或 git apply
使用 --3way
选项,git rebase
仍然可以)可以使用 git diff
输出的 index
行挑选出文件的更早版本。说到底,这应该没什么大不了的。
在任何情况下,合并实际上都会 运行 git diff
从基本提交到两个 "tips" (精心挑选的提交和 HEAD提交您尝试应用樱桃选择的内容)。要直观地查看发生了什么,您应该像往常一样从绘制提交图开始。 (我没有你的存储库,所以我会画一个 different 图,希望它足够接近。但是你应该自己画——或者让 Git 画,或者使用 gitk
或类似的东西。)
o--@ <-- branch (HEAD)
/
...--o--o
\
I--P--C--o <-- otherbranch
我在这里为各种提交提供了单字母名称:C
是我们要挑选的提交,P
是它的父提交。我在这里将我们当前的 (HEAD) 提交标记为 @
,尽管所有实际工作都将在索引和工作树中进行。 (幸运的是 git cherry-pick
要求索引和工作树为 "clean",除非您使用 -n
将多个樱桃 assemble 合并为一个大采摘,因此索引和工作-树将匹配提交 @
无论如何。)而且,我将提交 I
标记为 "important".
现在,考虑如果我们以 P
作为基础,C
作为一个提交,@
作为另一个提交进行三向合并会发生什么。当我们计算将 P
更改为 C
的指令时,我们得到了我们想要应用的差异:这非常简单。但是当我们计算将 P
更改为 @
的指令时,嗯,嗯。
我们在 I
中进行了一些重要更改。这些更改是 P
的一部分,即它们在我们的合并基础中。但在 @
中它们是 而不是 。合并的含义是 Git 会将这些重要更改视为我们正在尝试 un-做的事情。事实上,他们是!我们没有挑选 I
本身,因此我们必须撤消这些 I
更改以应用来自 C
.
无论那些 I
变化我们 "undoing" 不在 @
以 和 开始不影响任何来自 C
的更改,我们很好:它们已经撤消。如果,由于某种机会或目的,其中一个 I
改变 是 @
中的 (可能通过 @
的父级),那么这些都不是即使在 set 中,我们首先尝试撤消,所以我们再次很好。当这些变化 与 冲突,甚至只是 与 (的上下文)冲突时,P
-to-C
变化,我们有问题。
在这种情况下,Git 将在两个合并冲突区域之一中显示一些 I
更改。这些是我们试图挑选的部分。它们不一定被应用,它们只是我们必须解决的冲突的一部分。如果您将 merge.conflictStyle
设置为 diff3
——这是我通常推荐的——I
更改将显示为合并基础的一部分,因为合并基础 是 提交 P
,它本身基于 I
(即,P
的快照包括来自 I
的代码,除了我们在制作 [=22] 时更改它的地方=]).
所以,我不完全清楚你在问什么,但 正常看到,在合并冲突区域,更改与你正在处理的位无关-采摘。