部分樱桃 - 用Git挑选一个提交

oli*_*ver 484 git git-cherry-pick

我正在研究两个不同的分支:发布开发.

我注意到我仍然需要将一些提交给发布分支的更改集成到开发分支中.

问题是我不需要所有的提交,只有某些文件中的一些人,所以很简单

git cherry-pick bc66559
Run Code Online (Sandbox Code Playgroud)

没有办法.

当我做的时候

git show bc66559
Run Code Online (Sandbox Code Playgroud)

我可以看到差异,但实际上并不知道将其部分应用于我当前工作树的好方法.

Cas*_*bel 762

你在这里想要的核心是git add -p(-p是它的同义词--patch).这提供了一种检查内容的交互方式,让您决定是否应该进入每个大块,甚至可以在必要时手动编辑修补程序.

与樱桃挑选结合使用:

git cherry-pick -n <commit> # get your patch, but don't commit (-n = --no-commit)
git reset                   # unstage the changes from the cherry-picked commit
git add -p                  # make all your choices (add the changes you do want)
git commit                  # make the commit!
Run Code Online (Sandbox Code Playgroud)

(感谢Tim Henigan提醒我git-cherry-pick有--no-commit选项,感谢Felix Rabe指出你需要重置!如果你只想在提交中留下一些东西,你可以git reset <path>...用来取消那些文件.)

add -p如有必要,您当然可以提供特定路径.如果你已经从一个补丁,你可以替换cherry-pick使用apply.


如果你真的想要git cherry-pick -p <commit>(该选项不存在),你可以使用

git checkout -p <commit>
Run Code Online (Sandbox Code Playgroud)

这会将当前提交与您指定的提交区分开来,并允许您单独应用该差异中的数据.如果您提交的提交在您不感兴趣的提交的一部分中具有合并冲突,则此选项可能更有用.(但是,请注意,checkout不同于cherry-pick:checkout尝试<commit>完全应用的内容,cherry-pick应用diff的差异来自它的父指定的提交.这意味着checkout可以应用的不仅仅是那个提交,这可能比你想要的更多.)

  • 您可以通过运行`git cherry-pick --no-commit`跳过`reset HEAD ^`步骤. (38认同)
  • @Blixt这不对:checkout使文件与您指定的版本中的文件相同,但cherry-pick仅应用最近的更改. (11认同)
  • 还要考虑使用`git checkout -p COMMIT_YOU_WANT`,它基本上和这个答案一样,而不必运行`cherry-pick`,`reset`或`add`. (7认同)
  • 哇......那太快了!非常感谢!这对我有用.也许有一件事要从我这边添加:因为我不需要大部分的更改,我在樱桃选择之后做了一个`git add -i`并且最后一个`git reset --hard`来摆脱我不想要的改变. (2认同)
  • @Blixt 也就是说,如果在另一个分支上而不是您当前分支上的提交是 ABCDEF,`git checkout -p &lt;F&gt;` 不会* 只是让您从 F 获得更改,它会让您将 ABCDEF 全部混合在一起并让您整理出您想要的部分。将其缩减为 F 的一些更改是一种痛苦。另一方面,`git cherry-pick -n &lt;F&gt;` 只获取来自 F 的更改 - 如果其中一些更改发生冲突,它会帮助您了解如何正确合并。 (2认同)

Mik*_*icz 71

我知道我正在回答一个老问题,但看起来有一种新方法可以通过交互式检查来完成:

git checkout -p bc66559
Run Code Online (Sandbox Code Playgroud)

是否可以以交互方式从另一个git提交中挑选帅哥?

  • 请注意,这不仅应用(或提议应用)该提交中的更改,还应用自分支分歧以来的所有更改(至少在 Git 2.25.1 中)。 (2认同)

小智 37

假设您想要的更改位于您想要更改的分支的头部,请使用git checkout

对于单个文件:

git checkout branch_that_has_the_changes_you_want path/to/file.rb
Run Code Online (Sandbox Code Playgroud)

对于多个文件只是菊花链:

git checkout branch_that_has_the_changes_you_want path/to/file.rb path/to/other_file.rb
Run Code Online (Sandbox Code Playgroud)

  • 这会复制整个文件:不仅仅是更改. (5认同)

Chr*_*n.D 16

Mike Monkiewicz回答的基础上,您还可以指定一个或多个文件,以便从提供的sha1/branch中签出.

git checkout -p bc66559 -- path/to/file.java 
Run Code Online (Sandbox Code Playgroud)

这将允许您以交互方式选择要应用于当前版本文件的更改.

  • 如果文件的当前版本与该版本明显不同,则会出现问题.系统将提示您进行许多不相关的更改(这些更改不会出现在提交中).此外,您真正想要的更改可能会以"伪装形式"显示为当前的差异,而不是原始差异.您想要的原始差异可能会发生冲突,并且必须正确合并; 你不会有这个机会. (3认同)