git cherry-pick 说“...38c74d 是一个合并,但没有给出 -m 选项”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9229301/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
git cherry-pick says "...38c74d is a merge but no -m option was given"
提问by wufoo
I made some changes in my master branch and want to bring those upstream. when I cherry-pick the following commits however I get stuck on fd9f578 where git says:
我在我的主分支中做了一些更改,并希望将它们带到上游。当我选择以下提交时,我被困在 fd9f578 上,git 说:
$ git cherry-pick fd9f578
fatal: Commit fd9f57850f6b94b7906e5bbe51a0d75bf638c74d is a merge but no -m option was given.
What is git trying to tell me and is cherry-pick the right thing to be using here? The master branch does include changes to files which have been modified in the upstream branch, so I'm sure there will be some merge conflicts but those aren't too bad to straighten out. I know which changes are needed where.
git 想告诉我什么,并且挑选正确的东西在这里使用?master 分支确实包含对在上游分支中修改过的文件的更改,所以我确信会有一些合并冲突,但这些冲突并没有太糟糕而无法解决。我知道哪里需要进行哪些更改。
These are the commits I want to bring upstream.
这些是我想要向上游提交的提交。
e7d4cff added some comments...
23e6d2a moved static strings...
44cc65a incorporated test ...
40b83d5 whoops delete whitspace...
24f8a50 implemented global.c...
43651c3 cleaned up ...
068b2fe cleaned up version.c ...
fd9f578 Merge branch 'master' of ssh://extgit/git/sessions_common
4172caa cleaned up comments in sessions.c ...
回答by Borealid
The way a cherry-pick works is by taking the diff a changeset represents (the difference between the working tree at that point and the working tree of its parent), and applying it to your current branch.
樱桃挑选的工作方式是获取变更集表示的差异(此时工作树与其父工作树之间的差异),并将其应用于当前分支。
So, if a commit has two or more parents, it also represents two or more diffs - which one should be applied?
所以,如果一个提交有两个或更多的父项,它也代表两个或更多的差异——应该应用哪一个?
You're trying to cherry pick fd9f578
, which was a merge with two parents. So you need to tell the cherry-pick command which one against which the diff should be calculated, by using the -m
option. For example, git cherry-pick -m 1 fd9f578
to use parent 1 as the base.
您正在尝试挑选fd9f578
,这是与两个父母的合并。因此,您需要使用该-m
选项告诉cherry-pick 命令应该针对哪个计算差异。例如,git cherry-pick -m 1 fd9f578
使用父 1 作为基础。
I can't say for sure for your particular situation, but using git merge
instead of git cherry-pick
is generally advisable. When you cherry-pick a merge commit, it collapses allthe changes made in the parent you didn't specify to -m
into that one commit. You lose all their history, and glom together all their diffs. Your call.
对于您的特定情况,我不能肯定地说,但通常建议使用git merge
而不是git cherry-pick
。当您挑选合并提交时,它会将您未指定的父项中所做的所有更改折叠-m
到该提交中。你失去了他们所有的历史,把他们所有的差异都放在一起。您的来电。
回答by gavincook
-m
means the parent number.
-m
表示父编号。
From the git doc:
从 git 文档:
Usually you cannot cherry-pick a merge because you do not know which side of the merge should be considered the mainline. This option specifies the parent number (starting from 1) of the mainline and allows cherry-pick to replay the change relative to the specified parent.
通常您不能挑选合并,因为您不知道合并的哪一侧应该被视为主线。此选项指定主线的父级编号(从 1 开始)并允许cherry-pick 重播相对于指定父级的更改。
For example, if your commit tree is like below:
例如,如果您的提交树如下所示:
- A - D - E - F - master
\ /
B - C branch one
then git cherry-pick E
will produce the issue you faced.
然后git cherry-pick E
会产生你面临的问题。
git cherry-pick E -m 1
means using D-E
, while git cherry-pick E -m 2
means using B-C-E
.
git cherry-pick E -m 1
表示使用D-E
,而git cherry-pick E -m 2
表示使用B-C-E
。
回答by Daira Hopwood
@Borealid's answer is correct, but suppose that you don't care about preserving the exact merging history of a branch and just want to cherry-pick a linearized version of it. Here's an easy and safe way to do that:
@Borealid 的答案是正确的,但假设您不关心保留分支的确切合并历史记录,而只想挑选它的线性化版本。这是一个简单而安全的方法:
Starting state: you are on branch X
, and you want to cherry-pick the commits Y..Z
.
起始状态:您在 branch 上X
,并且您想挑选 commits Y..Z
。
git checkout -b tempZ Z
git rebase Y
git checkout -b newX X
git cherry-pick Y..tempZ
- (optional)
git branch -D tempZ
git checkout -b tempZ Z
git rebase Y
git checkout -b newX X
git cherry-pick Y..tempZ
- (可选的)
git branch -D tempZ
What this does is to create a branch tempZ
based on Z
, but with the history from Y
onward linearized, and then cherry-pick that onto a copy of X
called newX
. (It's safer to do this on a new branch rather than to mutate X
.) Of course there might be conflicts in step 4, which you'll have to resolve in the usual way (cherry-pick
works very much like rebase
in that respect). Finally it deletes the temporary tempZ
branch.
这样做的目的是创建一个tempZ
基于的分支Z
,但是将历史从Y
以后线性化,然后将其挑选到一个X
被调用的副本上newX
。(在新分支上执行此操作比在 mutate 上执行此操作更安全X
。)当然,步骤 4 中可能存在冲突,您必须以通常的方式解决(在这方面的cherry-pick
工作方式非常相似rebase
)。最后它删除临时tempZ
分支。
If step 2 gives the message "Current branch tempZ is up to date", then Y..Z
was already linear, so just ignore that message and proceed with steps 3 onward.
如果第 2 步给出消息“当前分支 tempZ 是最新的”,则Y..Z
已经是线性的,因此只需忽略该消息并继续执行第 3 步。
Then review newX
and see whether that did what you wanted.
然后查看newX
并查看是否符合您的要求。
(Note: this is not the same as a simple git rebase X
when on branch Z
, because it doesn't depend in any way on the relationship between X
and Y
; there may be commits between the common ancestor and Y
that you didn't want.)
(注意:这与git rebase X
在 branch 上的简单不同Z
,因为它不以任何方式依赖于X
和之间的关系Y
;在共同祖先和Y
您不想要的之间可能存在提交。)
回答by Kay V
Simplify. Cherry-pick the commits. Don't cherry-pick the merge.
简化。樱桃挑选提交。不要随意挑选合并。
Here's a rewrite of the accepted answer that ideally clarifies the advantages/risks of possible approaches:
这是对已接受答案的重写,理想地阐明了可能方法的优点/风险:
You're trying to cherry pick fd9f578, which was a merge with two parents.
你试图挑选 fd9f578,这是与两个父母的合并。
Instead of cherry-picking a merge, the simplest thing is to cherry pick the commit(s) you actually want from each branch in the merge.
不是挑选合并,最简单的方法是从合并中的每个分支中挑选出您真正想要的提交。
Since you've already merged, it's likely all your desired commits are in your list. Cherry-pick them directly and you don't need to mess with the merge commit.
由于您已经合并,很可能所有您想要的提交都在您的列表中。直接挑选它们,您不需要弄乱合并提交。
explanation
解释
The way a cherry-pick works is by taking the diff that a changeset represents (the difference between the working tree at that point and the working tree of its parent), and applying the changeset to your current branch.
樱桃挑选的工作方式是获取变更集表示的差异(此时工作树与其父级工作树之间的差异),并将变更集应用于当前分支。
If a commit has two or more parents, as is the case with a merge, that commit also represents two or more diffs. The error occurs because of the uncertainty over which diff should apply.
如果一个提交有两个或更多的父项,就像合并的情况一样,那个提交也代表两个或更多的差异。发生错误是因为不确定应该应用哪个差异。
alternatives
备择方案
If you determine you need to include the merge vs cherry-picking the related commits, you have two options:
如果您确定需要包含合并与挑选相关提交,您有两个选择:
(More complicated and obscure; also discards history) you can indicate which parent should apply.
Use the
-m
option to do so. For example,git cherry-pick -m 1 fd9f578
will use the first parent listed in the merge as the base.Also consider that when you cherry-pick a merge commit, it collapses allthe changes made in the parent you didn't specify to
-m
into that one commit. You lose all their history, and glom together all their diffs. Your call.
(Simpler and more familiar; preserves history) you can use
git merge
instead ofgit cherry-pick
.- As is usual with
git merge
, it will attempt to apply all commits that exist on the branch you are merging, and list them individually in your git log.
- As is usual with
(更复杂和晦涩;也丢弃历史)您可以指出应该申请哪个父级。
使用该
-m
选项执行此操作。例如,git cherry-pick -m 1 fd9f578
将使用合并中列出的第一个父项作为基础。还要考虑到,当您挑选合并提交时,它会将您未指定的父项中所做的所有更改折叠
-m
到该提交中。你失去了他们所有的历史,把他们所有的差异都放在一起。您的来电。
(更简单,更熟悉;保留历史)您可以使用
git merge
代替git cherry-pick
.- 与通常一样
git merge
,它会尝试应用您正在合并的分支上存在的所有提交,并在您的 git 日志中单独列出它们。
- 与通常一样
回答by ephemerr
Simplification of @Daira Hopwood method good for picking one single commit. Need no temporary branches.
@Daira Hopwood 方法的简化有利于选择单个提交。不需要临时分支。
In the case of the author:
在作者的情况下:
- Z is wanted commit (fd9f578)
- Y is commit before it
- X current working branch
- Z 被通缉 (fd9f578)
- Y 在它之前提交
- X 当前工作分支
then do:
然后做:
git checkout Z # move HEAD to wanted commit
git reset Y # have Z as changes in working tree
git stash # save Z in stash
git checkout X # return to working branch
git stash pop # apply Z to current branch
git commit -a # do commit