我正在研究 2 个不同的分支:发布和开发。
我注意到我仍然需要将提交给发布分支的一些更改集成回开发分支。
问题是我不需要所有的提交,只需要某些文件中的一些大块,所以一个简单的
git cherry-pick bc66559
不成功。
当我做一个
git show bc66559
我可以看到差异,但真的不知道将其部分应用于我当前的工作树的好方法。
我正在研究 2 个不同的分支:发布和开发。
我注意到我仍然需要将提交给发布分支的一些更改集成回开发分支。
问题是我不需要所有的提交,只需要某些文件中的一些大块,所以一个简单的
git cherry-pick bc66559
不成功。
当我做一个
git show bc66559
我可以看到差异,但真的不知道将其部分应用于我当前的工作树的好方法。
您在这里想要的核心是git add -p
(-p
是 的同义词--patch
)。这提供了一种添加内容的交互式方式,让您决定是否每个大块应该进入,甚至让您在必要时手动编辑补丁。
将其与cherry-pick结合使用:
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!
(感谢 Tim Henigan 提醒我git-cherry-pick
有一个--no-commit
选项,感谢 Felix Rabe 指出您需要git reset
. 如果您只想在提交中保留一些内容,您可以使用git reset <path>...
unstage 仅这些文件。)
add -p
如有必要,您可以提供特定路径。如果你从一个补丁开始,你可以cherry-pick
用apply
.
如果您真的想要git cherry-pick -p <commit>
(该选项不存在),您可以使用
git checkout -p <commit>
这会将当前提交与您指定的提交进行比较,并允许您单独从该差异中应用大块。如果您正在拉入的提交在您不感兴趣的部分提交中存在合并冲突,则此选项可能更有用。(但是,请注意,这checkout
与cherry-pick
:checkout
尝试<commit>
完全应用的内容不同,而cherry-pick
应用差异来自它的父级的指定提交。这意味着checkout
可以应用的不仅仅是那个提交,这可能比你想要的要多。)
假设您想要的更改位于您想要更改的分支的开头,请使用 git checkout
对于单个文件:
git checkout branch_that_has_the_changes_you_want path/to/file.rb
对于多个文件只是菊花链:
git checkout branch_that_has_the_changes_you_want path/to/file.rb path/to/other_file.rb
基于Mike Monkiewicz 的回答,您还可以指定一个或多个文件以从提供的 sha1/branch 中检出。
git checkout -p bc66559 -- path/to/file.java
这将允许您以交互方式选择要应用于当前文件版本的更改。
如果您想在命令行上指定文件列表,并在单个原子命令中完成整个操作,请尝试:
git apply --3way <(git show -- list-of-files)
--3way
:如果补丁没有完全应用,Git 将创建合并冲突,以便您可以运行git mergetool
. 省略--3way
将使 Git 放弃不能干净应用的补丁。
用于git format-patch
切出您关心的提交部分并将git am
其应用到另一个分支
git format-patch <sha> -- path/to/file
git checkout other-branch
git am *.patch
如果“部分采摘”意味着“在文件中,选择一些更改但丢弃其他更改”,则可以通过引入git stash
:
git reset HEAD^
将整个精心挑选的提交转换为未分级的工作更改。git stash save --patch
:以交互方式选择不需要的材料进行存储。git commit
git stash drop
.提示:如果您为不需要的更改的存储命名:git stash save --patch junk
那么如果您现在忘记执行 (6),稍后您将识别存储的内容。
实际上,这个问题的最佳解决方案是使用checkout
表扬
git checkout <branch> <path1>,<path2> ..
例如,假设您在master,您想要从dev1project1/Controller/WebController1.java
和进行更改project1/Service/WebService1.java
,您可以使用以下命令:
git checkout dev1 project1/Controller/WebController1.java project1/Service/WebService1.java
这意味着主分支仅在这两个路径上从dev1更新。