本文翻译自:git cherry-pick says “…38c74d is a merge but no -m option was given”

I made some changes in my master branch and want to bring those upstream. 我在master分支中进行了一些更改,并希望将其引入上游。 when I cherry-pick the following commits however I get stuck on fd9f578 where git says: 当我选择以下提交时,但是我陷入了git说的fd9f578上:

$ 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? git试图告诉我什么,在这里选择正确的选择是正确的选择吗? 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. master分支确实包含对文件的更改,这些更改已在上游分支中进行了修改,因此我敢肯定会有一些合并冲突,但是合并冲突还算可以解决。 I know which changes are needed where. 我知道哪些地方需要更改。

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

#1楼

参考:https://stackoom.com/question/cixh/git-cherry-pick说-c-d是合并-但未提供-m选项


#2楼

@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. @Borealid的答案是正确的,但假设您不关心保留分支的确切合并历史,只想选择线性化的分支即可。 Here's an easy and safe way to do that: 这是一种简单安全的方法:

Starting state: you are on branch X , and you want to cherry-pick the commits Y..Z . 起始状态:您在分支X ,并且想要选择提交Y..Z

  1. git checkout -b tempZ Z
  2. git rebase Y
  3. git checkout -b newX X
  4. git cherry-pick Y..tempZ
  5. (optional) git branch -D 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 . 这是基于Z创建分支tempZ ,但是将Y以后的历史线性化,然后将其樱桃拾取到名为newXX副本上。 (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). (在新分支上执行此操作比对X进行突变更安全。)当然,在第4步中可能会发生冲突,您必须以通常的方式解决(在这方面, cherry-pick工作原理与rebase非常相似) )。 Finally it deletes the temporary tempZ branch. 最后,它删除临时的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.) (注意:这与在分支Z上的简单git rebase X ,因为它不以任何方式取决于XY之间的关系;在共同祖先和Y之间可能存在您未提交的提交”不想。)


#3楼

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: 如果确定需要包括合并与挑选相关提交的比较,则有两种选择:

  1. (More complicated and obscure; also discards history) you can indicate which parent should apply. (更加复杂和晦涩;也将丢弃历史记录),您可以指明应采用哪个家长。

    • Use the -m option to do so. 使用-m选项来执行此操作。 For example, git cherry-pick -m 1 fd9f578 will use the first parent listed in the merge as the base. 例如, git cherry-pick -m 1 fd9f578将使用合并中列出的第一个父对象作为基础。

    • Also consider that when you cherry-pick a merge commit, it collapses all the changes made in the parent you didn't specify to -m into that one commit . 还要考虑一下,当您选择一个合并提交时,它会将您未指定对-m的父级所做的所有更改折叠到那个提交中 You lose all their history, and glom together all their diffs. 您会失去他们的所有历史,并将他们所有的差异混在一起。 Your call. 你的来电。

  2. (Simpler and more familiar; preserves history) you can use git merge instead of git cherry-pick . (更简单,更熟悉;保留历史记录),您可以使用git merge代替git 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. git merge ,它将尝试应用要合并的分支上存在的所有提交,并在git日志中单独列出它们。

#4楼

Simplification of @Daira Hopwood method good for picking one single commit. @Daira Hopwood方法的简化适用于选择一个提交。 Need no temporary branches. 不需要临时分支。

In the case of the author: 对于作者而言:

  • Z is wanted commit (fd9f578) Z是通缉犯(fd9f578)
  • Y is commit before it Y在它之前提交
  • X current working branch 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

#5楼

-m means the parent number. -m表示父编号。

From the git doc: 从git doc:

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 DE , while git cherry-pick E -m 2 means using BCE . git cherry-pick E -m 1表示使用DE ,而git cherry-pick E -m 2表示使用BCE


#6楼

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. 您正在尝试挑选fd9f578 ,它是与两个父母合并的。 So you need to tell the cherry-pick command which one against which the diff should be calculated, by using the -m option. 因此,您需要通过使用-m选项来告诉cherry-pick命令应针对哪个差异计算差异。 For example, git cherry-pick -m 1 fd9f578 to use parent 1 as the base. 例如, 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. 对于您的特定情况,我无法确定,但是通常建议使用git merge而不是git cherry-pick When you cherry-pick a merge commit, it collapses all the changes made in the parent you didn't specify to -m into that one commit . 当您选择一个合并提交时,它会将您未指定对-m的父级所做的所有更改折叠到那个提交中 You lose all their history, and glom together all their diffs. 您会失去他们的所有历史,并将他们所有的差异混在一起。 Your call. 你的来电。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐