【问题标题】:git cherry-pick says "...38c74d is a merge but no -m option was given"git cherry-pick 说“...38c74d 是一个合并,但没有给出 -m 选项”
【发布时间】:2012-03-03 00:17:23
【问题描述】:

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

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

git 试图告诉我什么,并且挑选合适的东西在这里使用? master 分支确实包含对上游分支中已修改的文件的更改,因此我确信会有一些合并冲突,但这些冲突还不错,无法理顺。我知道哪里需要进行哪些更改。

这些是我想带到上游的提交。

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

【问题讨论】:

    标签: git merge rebase cherry-pick git-cherry-pick


    【解决方案1】:

    简化。樱桃挑选提交。不要挑选合并。

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

    1. (更复杂和模糊;也丢弃历史记录)您可以指明应该应用哪个父级。
    • 使用-m 选项来执行此操作。例如,git cherry-pick -m 1 fd9f578 将使用合并中列出的第一个父级作为基础。

    • 还请考虑,当您选择合并提交时,它会将 所有您未指定到 -m 的父项中所做的更改折叠到该 一个提交。你失去了他们所有的历史,并把他们所有的差异放在一起。您的来电。

    1. (更简单、更熟悉;保留历史记录)您可以使用git merge 而不是git cherry-pick
    • git merge 一样,它会尝试应用您正在合并的分支上存在的所有提交,并在您的 git 日志中单独列出它们。

    【讨论】:

    • git merge 不是cherry-pick的替代品,因为它还会合并基于合并分支的提交。我实际上在这里有一个整洁的图表,但是堆栈溢出不允许在 cmets 中进行格式化。想象一下,您有单独的发布分支 R、开发分支 D 和功能分支 F 和 G。F 合并到 D 中,然后 G 启动并合并到 D。业务决定只有来自 G 的更改应该进入,并且您希望这些更改进入发布分支 R,您可以选择合并提交或 R 上的 rebase --onto 分支 G。替代方法是 git rebase --onto
    • -m 选项是什么意思?
    【解决方案2】:

    -m 表示父编号。

    来自 git 文档:

    通常您不能挑选合并,因为您不知道合并的哪一侧应该被视为主线。此选项指定父编号(从 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

    1. git checkout -b tempZ Z
    2. git rebase Y
    3. git checkout -b newX X
    4. git cherry-pick Y..tempZ
    5. (可选)git branch -D tempZ

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

    如果第 2 步给出消息“当前分支 tempZ 是最新的”,则 Y..Z 已经是线性的,因此请忽略该消息并继续执行第 3 步。

    然后查看newX,看看它是否符合您的要求。

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

    【讨论】:

    • git rebase YCurrent branch tempZ is up to date
    • 我认为这意味着Y..Z 已经是线性的。因此,您可以忽略该消息并继续执行第 3 步和第 4 步。
    • 有趣的想法,我必须把它画在纸上才能完全理解发生了什么=D
    • 太棒了。整个范围的 git cherry-pick 抱怨缺少 -m 选项或提供了该选项。你的解决方案是黄金。 (一个建议:删除 tempZ 分支之后)
    • 这太棒了!我一直在努力挑选樱桃,只有这样才有意义。我选择的字母有点麻烦(有些分支和提交是大写字母,有些分支是小写)
    【解决方案4】:

    @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
    

    【讨论】:

    • 这当然会丢失与原始提交相关的元数据。我想它是否更简单是一个见仁见智的问题。当我想要丢失元数据并且只保留整体代码更改时,我确实会使用它。请注意,即使 Y 不是 Z 的直接父级,它也可以工作(在这种情况下,更改将被压缩)。
    【解决方案5】:

    cherry-pick 的工作方式是获取变更集所代表的差异(此时工作树与其父工作树之间的差异),并将其应用于当前分支。

    所以,如果一个提交有两个或多个父级,它也代表两个或多个差异 - 应该应用哪一个?

    您正在尝试挑选 fd9f578,这是与两个父母的合并。因此,您需要使用-m 选项告诉cherry-pick 命令应该根据哪个计算差异。例如,git cherry-pick -m 1 fd9f578 使用父级 1 作为基础。

    我不能确定您的具体情况,但通常建议使用git merge 而不是git cherry-pick。当您选择合并提交时,它会将所有您未指定到 -m 的父项中所做的更改折叠到该一个提交中。你失去了他们所有的历史,并把他们所有的差异放在一起。您的来电。

    【讨论】:

    • @wufoo 您可能还应该了解git rebase - 这就像一个合并,但不是集成两个分支,而是将一个移植到另一个之上。
    • 你怎么知道父母的号码?
    • @Anentropic 1 是“第一父”,2 是“第二父”,依此类推。顺序是它们在提交中列出的顺序(由git show 等查看)。
    • @lkraav 你也可以通过git reset --hard HEAD@{1} 找回丢失的提交。 git reset 不仅限于在历史上“倒退”。 git checkout -b mybranch HEAD@{1} 也可以。
    • 警告:git merge 可能会产生意想不到的后果。该命令将添加父分支上存在的所有其他(旧)提交。通常人们选择挑选是因为他们不想要其他提交。确保您仔细检查您是否只实施了您想要的更改!
    猜你喜欢
    • 2016-08-26
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 2018-04-13
    • 1970-01-01
    相关资源
    最近更新 更多