首页 文章

git cherry-pick说“...... 38c74d是合并但没有给出-m选项”

提问于
浏览
349

我在我的主分支中进行了一些更改,并希望将这些更改带到上游 . 当我樱桃挑选以下提交但是我被卡在fd9f578上,git说:

$ git cherry-pick fd9f578
fatal: Commit fd9f57850f6b94b7906e5bbe51a0d75bf638c74d is a merge but no -m option was given.

git试图告诉我什么是樱桃挑选正确的东西在这里使用?主分支确实包含对在上游分支中已修改的文件的更改,因此我确信会出现一些合并冲突,但这些并不太难以理顺 . 我知道哪些地方需要改变 .

这些是我想要上传的提交 .

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

5 回答

  • 0

    简化@Daira Hopwood方法,有利于选择一个提交 . 不需要临时分支机构 .

    就作者而言:

    • Z需要提交(fd9f578)

    • Y在它之前提交

    • X当前工作分支

    然后做:

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

    这是对已接受答案的重写,理想地阐明了可能方法的优点/风险:

    你正试图挑选fd9f578,这是与两个父母的合并 .

    而不是挑选合并,最简单的事情是从合并中的每个分支中挑选您真正想要的提交 .

    由于您已经合并,因此您的列表中可能包含所有您想要的提交 . Cherry直接挑选它们,你不需要搞乱合并提交 .

    解释

    cherry-pick工作的方式是通过获取changeset表示的diff(该点的工作树与其父工作树之间的差异),并将changeset应用于当前分支 .

    如果提交具有两个或更多个父项,就像合并的情况一样,该提交也表示两个或更多个差异 . 出现错误是因为应该应用差异的不确定性 .

    替代品

    如果您确定需要包含合并与挑选相关提交,则有两种选择:

    • (更复杂和模糊;也丢弃历史记录)您可以指出应该应用哪个父级 .

    • 使用 -m 选项执行此操作 . 例如, git cherry-pick -m 1 fd9f578 将使用合并中列出的第一个父级作为基础 .

    • 还要考虑当你挑选合并提交时,它会将 all 在您未指定的父项中所做的更改折叠到 one commit 中 . 你失去了他们所有的历史,并将他们所有的差异融合在一起 . 你的来电 .

    • (更简单,更熟悉;保留历史记录)您可以使用 git merge 而不是 git cherry-pick .

    • git merge 一样,它将尝试应用您正在合并的分支上存在的所有提交,并在git日志中单独列出它们 .

  • 437

    樱桃选择的工作方式是通过取一个变量集表示的差异(该点的工作树与其父工作树之间的差异),并将其应用于当前分支 .

    因此,如果一个提交有两个或更多父母,它也代表两个或更多的差异 - 应该应用哪一个?

    你正试图挑选 fd9f578 ,这是与两个父母的合并 . 因此,您需要通过使用 -m 选项告诉cherry-pick命令应该计算diff的哪一个 . 例如, git cherry-pick -m 1 fd9f578 使用父1作为基础 .

    我无法确定您的具体情况,但通常建议使用 git merge 而不是 git cherry-pick . 当您选择合并提交时,它会将您未指定的父级所做的更改 all 折叠到 one commit 中 . 你失去了他们所有的历史,并将他们所有的差异融合在一起 . 你的来电 .

  • 19

    -m 表示父编号 .

    从git doc:

    通常你不能挑选合并,因为你不知道合并的哪一边应该被认为是主线 . 此选项指定主线的父编号(从1开始),并允许cherry-pick重放相对于指定父级的更改 .

    例如,如果您的提交如下:

    - A - D - E - F -   master
       \     /
        B - C           branch one
    

    git cherry-pick E 将导致您面临的问题 .

    git cherry-pick E -m 1 表示使用 D-E ,而 git cherry-pick E -m 2 表示使用 B-C-E .

  • 3

    @ Borealid的答案是正确的,但是假设您不关心保留分支的精确合并历史,只是想挑选它的线性化版本 . 这是一种简单安全的方法:

    开始状态:你在分支 X ,你想要挑选提交 Y..Z .

    • git checkout -b tempZ Z

    • git rebase Y

    • git checkout -b newX X

    • git cherry-pick Y..tempZ

    • (可选) git branch -D tempZ

    这样做是为了创建一个基于 Z 的分支 tempZ ,但是从 Y 开始的历史线性化,然后将其挑选到 X 的副本上,称为 newX . (在新的分支上执行此操作更安全,而不是改变 X . )当然,步骤4中可能存在冲突,您必须以通常的方式解决( cherry-pick 在这方面非常像 rebase ) . 最后,它删除临时 tempZ 分支 .

    如果一步2给出了消息"Current branch tempZ is up to date",然后 Y..Z 已经是线性的,所以只需忽略该消息并继续执行步骤3 .

    然后查看 newX 并查看是否符合您的要求 .

    (注意:当分支 Z 时,这与简单的 git rebase X 不同,因为它不依赖于 XY 之间的关系;可能在共同的祖先和_40803之间提交了你不想要的 . )

相关问题