在一定程度上用Git选择提交

我正在研究2个不同的分支:释放发展

我注意到我仍然需要将一些提交给释放分支的更改集成到发展分支中。

问题是我不需要所有的提交,只有一些块在某些文件,所以一个简单的

git cherry-pick bc66559

这是行不通的。

当我做

git show bc66559

我可以看到差异,但真的不知道一个好方法,部分应用到我目前的工作树。

145994 次浏览

这里需要的核心内容是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>...来取消这些文件。)

如果需要,您可以提供到add -p的特定路径。如果你从一个补丁开始,你可以用apply替换cherry-pick


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

git checkout -p <commit>

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

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

对于单个文件:

git checkout branch_that_has_the_changes_you_want path/to/file.rb

对于多个文件只需Daisy chain:

git checkout branch_that_has_the_changes_you_want path/to/file.rb path/to/other_file.rb

我知道我在回答一个老问题,但似乎有一种新的方式来进行交互式检查:

git checkout -p bc66559

这要归功于我可以从另一个git提交中交互式地选择大块吗?

如果“partial cherry picking”意味着“在文件中,选择一些更改,但放弃其他更改”,可以通过引入git stash来完成:

  1. 做完整的樱桃采摘。
  2. git reset HEAD^将整个选定的提交转换为未分阶段的工作更改。
  3. 现在git stash save --patch:交互选择不需要的材料来隐藏。
  4. Git从工作副本中回滚存储的更改。
  5. # EYZ0
  6. 扔掉不需要的更改:git stash drop

提示:如果你给隐藏的不需要的更改起一个名字:git stash save --patch junk,那么如果你现在忘记做(6),以后你会认出隐藏的是什么。

迈克Monkiewicz答案的基础上,您还可以指定一个或多个文件来从所提供的sha1/branch签出。

git checkout -p bc66559 -- path/to/file.java

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

如果你想在命令行上指定一个文件列表,并在一个原子命令中完成所有事情,尝试:

# EYZ0

--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

实际上,这个问题的最佳解决方案是使用checkout推荐

git checkout <branch> <path1>,<path2> ..

例如,假设你在,你想要从dev1project1/Controller/WebController1.javaproject1/Service/WebService1.java的变化,你可以使用这个:

git checkout dev1 project1/Controller/WebController1.java project1/Service/WebService1.java

这意味着分支只从这两条路径上的dev1进行更新。