如何在提交树中的其他地方应用来自特定 Git 提交的更改?

How do I apply changes from a specific Git commit somewhere else in the commit tree?

假设我在 git 存储库 'master' 和 'feature' 中有两个分支。这两个分支在某些方面有所不同。现在我想从 'feature' 分支上的提交 '0123456789abcdef' 中对 'script.py' 进行确切的更改,并将这些更改应用到 [=24= 开头的 'script.py' 的相应行]分支。
git cherry-pick 对我来说似乎是显而易见的选择,但它并不完全符合我的要求。问题是 git cherry-pick 使 'master' 分支更新了 'feature' 上的所有更改,直到提交 '​​0123456789abcdef'。
我不希望应用所有这些更改。我只想要在提交“0123456789abcdef”中发生的确切更改 - 仅此而已。我认为如果我能够以某种方式利用共同的历史来找出相对于 'feature' 的提交,相应的更改行可能在 'master' 中移动的位置,而不是在 'feature' 上应用所有这些先前的更改,那将是明智的。 =24=].
我怎样才能做到这一点?当然,我可以从 git diff 的输出中复制并粘贴它,但是我对 Git 的了解有点好,在我看来它必须有更好的方法来做到这一点,我只是还不知道.

编辑: 看来上述行为一定是错误的结果,我无法再重现。基于,我重复了cherry-pick的正确过程,它产生了我想要的结果。

在此声明中:

git cherry-pick seems like the obvious choice to me here, but it does not do exactly what I want. The trouble is that git cherry-pick brings the 'master' branch up to date with all the changes on 'feature' up to commit '0123456789abcdef'.

您已将 cherry-pick 与合并混为一谈。如果你要 运行:

git checkout master
git merge 0123456789abcdef

that会找到master当前tip commit的merge base,然后commit 0123456789abcdef,按你说的做。但是 git cherry-pick 0123456789abcdef 找到了 0123456789abcdefparent 提交,然后在此处涉及的三个提交上调用 Git 的合并引擎。

效果是git cherry-pick会找出从0123456789abcdef^——0123456789abcdef的parent——到0123456789abcdef的变化,并应用到当前或 HEAD 提交。这会影响到不止一个文件,如果不止一个文件有任何从0123456789abcdef^0123456789abcdef的差异(使用git diff 0123456789abcdef^ 0123456789abcdef,或者更简单地说,git show 0123456789abcdef,看看;注意0123456789abcdef 不能是合并提交)。

如果您只想应用一个特定文件的 0123456789abcdef^0123456789abcdef 更改,请使用 git cherry-pick -n 以便 git cherry-pick 完成工作的初始部分, 但在提交结果之前停止。这使您有机会使用 git resetgit restore 撤销对其他文件的更改。 (如果使用 git reset,请务必提供文件名;git restore 是 Git 2.23 中的新内容,在这方面是 git reset 的一个更有限但更灵活的变体.)

请注意 git cherry-pick 相当于:

git diff master 0123456789abcdef

也就是说,它不希望使任何文件的 master 版本 匹配 0123456789abcdef 中任何文件的版本。 Git 最终会做的是 three-way 合并,结合 diffs 产生的:

git diff --find-renames 0123456789abcdef^ HEAD

(即 you 相对于 0123456789abcdef 的 parent 所做的更改)与由以下人员生成的内容:

git diff --find-renames 0123456789abcdef^ 0123456789abcdef

(即,他们 相对于他们自己的 parent 发生了什么变化)。然后将合并的更改应用到来自 0123456789abcdef^ 的快照:这会将您的更改添加到他们的 parent,加上他们对他们的 parent 的更改。最终结果(如果没有冲突)是您将他们的更改添加到当前提交中,其中“他们的更改”是相对于他们提交的 parent 的快照;但这也说明了他们的提交 parent 和您的提交之间的任何直线运动,甚至 file-name-changes。

因此,根据您的问题,cherry-pick似乎是的答案。如果不是,您将需要提供更多信息来说明为什么会这样。