【问题标题】:git - skipping specific commits when merginggit - 合并时跳过特定提交
【发布时间】:2010-10-18 04:46:17
【问题描述】:

我已经使用 Git 大约一年了,觉得它很棒,但我刚刚开始了该项目的第二个版本并为其创建了一个新分支。我正在努力寻找处理未来事情的最佳方式。

我有两个分支,分别称为 master10(用于 v1)和 master20(用于 v2)。我一直在 master10 分支的 v1 中进行错误修复,并开发 master20 的新内容。每当我进行错误修复时,我都会通过检查 master20 并执行 git merge master10 将其合并到 v2 中。到目前为止一切顺利。

然而,现在我在 v1 中做出了我不希望在 v2 中进行的更改,但我想继续合并其他错误修复。我如何告诉 Git 跳过特定的提交(或一系列提交),但今后我仍想合并其他错误修复。

我认为git rebase 可能是我需要的,但读了文档,我的脑袋几乎要爆炸了。

我想我想要的是一个类似于“git sync”的命令,它告诉 git 两个分支现在是同步的,并且将来只会合并来自这个同步点的提交。

任何帮助表示赞赏。

【问题讨论】:

    标签: git version-control


    【解决方案1】:

    您可以为此使用 git-cherry pick:

    git cherry-pick $(git merge-base HEAD origin/branch)..$(git rev-parse <offending-commit-hash>^)
    git cherry-pick <offending-commit-hash>..$(git rev-parse origin/branch)
    

    这会从当前 HEAD 和 origin/branch 的最后一次常见提交中挑选所有提交,直到提交被忽略(注意 ^ 告诉cherry-pick 在该提交的父级处停止)。

    第二个命令从&lt;offending-commit-hash&gt; 和origin/branch 中挑选所有内容。

    请注意,如果需要跳过提交以合并其他补丁,则可能仍需要进行一些修改(git 将停止 cherry-pick 并告诉您解决冲突)。

    【讨论】:

      【解决方案2】:

      例如,如果您想将分支“maint”上的大部分但不是所有提交合并到“master”,您可以这样做。它需要一些工作——如上所述,通常的用例是合并分支中的所有内容——但有时会发生你对不应该集成回来的发布版本的更改(也许该代码的已经被master取代了),那么你如何表示呢?来了……

      所以让我们假设 maint 已经应用了 5 个更改,其中一个 (maint~3) 不会合并回 master,尽管所有其他的都应该合并。您分三个阶段执行此操作:实际合并该阶段之前的所有内容,告诉 git 将 maint~3 标记为已合并,即使未合并,然后合并其余部分。神奇的是:

      bash <master>$ git merge maint~4
      bash <master>$ git merge -s ours maint~3
      bash <master>$ git merge maint
      

      第一个命令将您麻烦的维护提交之前的所有内容合并到 master 上。默认的合并日志消息将说明您正在合并“分支'维护'(早期部分)”。

      第二个命令合并了麻烦的 maint~3 提交,但是“-s ours”选项告诉 git 使用特殊的“合并策略”,实际上,它的工作原理是简单地保留要合并的树并忽略提交您正在完全合并。但它仍然会以 HEAD 和 maint~3 作为父级进行新的合并提交,因此修订图现在显示 maint~3 已合并。所以实际上你可能也想使用 git merge 的 -m 选项来解释 maint~3 提交实际上被忽略了!

      最后的命令只是简单地将其余的 maint (maint~2..maint) 合并到 master 中,这样你们就可以再次同步了。

      【讨论】:

      • 我认为,如果您需要推迟合并该提交,您别无选择,只能跳过它(merge -s ours),然后使用cherry-pick 命令应用它。一旦提交可以从 master 访问,它就不能再次合并 - 避免两次合并相同的更改是 git 的主要目标之一。
      • 关于您的子分支示例:我怀疑一旦您合并了子分支,您的情况与我的帖子第二步之后的情况完全相同。创建额外的分支对提交关系没有影响。
      • 只是出于兴趣,如果您只想省略一个更改,为什么不只进行一次合并然后还原该更改集,而不是执行三个合并?这将导致更少的变更集被提交到存储库和更明确的历史记录。
      • 通常更容易明确地命名提交。因此,您只需要查看待合并分支的 git 日志并记下不应合并的提交的哈希值和之前的哈希值 - 而不是计算提交...
      • @MarkBooth:您要跳过的提交可能与您要合并的分支存在巨大冲突。跳过它而不是修复冲突然后恢复该更改并修复更容易再次发生冲突
      【解决方案3】:

      对于这种情况,而不是 revert 或 cherry-pick,您需要让 git 考虑您跳过的更改比您所做的更改更早。

      所以:

      1. 在要跳过的提交之前合并最后一个提交。当然,这将合并之前的所有提交。 git merge ccc
      2. 合并你想跳过的提交。 git merge fff --no-commit
      3. 暂存任何合并,取消暂存所有更改,撤消所有更改。 (也许有一些简单的命令,但我只是在 UI 中完成这部分 - 但你知道怎么做)
      4. 完成空合并git merge --continue
      5. 在您要跳过的提交之后合并提交。 git merge source-branch-head

      在第 4 步之后,git 会认为您的分支比该提交更新,因为您已经处理了它(通过选择保留您的事物版本)。

      【讨论】:

        【解决方案4】:

        听起来像是 'git cherry-pick' 的经典案例 https://git-scm.com/docs/git-cherry-pick 它完全符合听起来的样子

        【讨论】:

        • “听起来像是经典案例” top :D
        【解决方案5】:

        我的project 的一种广告,它基本上包装了@araqnid 描述的过程。

        这是一种引入以下 GIT 流程的助手:

        • 每天/每周都有关于从维护分支到 dev/master 分支的未决合并的通知
        • 分支维护者检查状态并自行决定是否需要所有提交并阻止其中一些提交或要求开发人员自行阻止。最终维护分支并入上游。

        项目页面的引用:

        根据工作流程,可以进行维护或 客户特定的分支以及主分支。这些 分支也称为 LTS 分支。

        热修复通常会进入错误所在的分支 报告,然后将提交合并回主分支。

        一般做法是让所有分支完美同步 主人,即你想看到一个特定的 branch 和 master 了解master是否包含所有 功能和错误修正。

        但有时您不想要特定的提交,因为它们是 客户特定的,其他用户不可见。或者你的 master 分支分歧很大,以至于它需要完全不同 解决问题的方法,甚至更好,问题不再存在 在那里。

        同样,如果从 master 中挑选樱桃进入维护分支 生成的提交应在 master 中被阻止。

        【讨论】:

          【解决方案6】:

          恕我直言,最合乎逻辑的做法是合并所有内容,然后使用 git revert (commit_you_dont_want) 将其删除。

          例子:

          git merge master
          git revert 12345678
          

          如果您有多个“忽略”提交,或者想要编辑还原消息:

          git merge master
          git revert -n 123456
          git revert -n abcdef
          git commit -m "... Except commits 123456 and abcdef"
          

          那么你的历史可能看起来像:

          | ... Except 123456 and abcdef
          |\ Merge branch 'master' into 'your_branch'
          

          如果您的冲突仅涉及这些“忽略”提交,您可以使用:

          git merge master -X ours
          

          因此,您的版本将持续存在于另一个版本之上。即使没有错误消息,您仍然可以“还原”那些不需要的提交,因为它们可能有其他没有冲突的更改,而您仍然不想要它们。

          如果您遇到的冲突不仅涉及“忽略”提交,您应该手动解决它们,并且您可能需要在还原期间再次解决它们。

          【讨论】:

          • 如果您稍后想将那些恢复的提交合并到有问题的分支中,Git 还会忽略它们吗?
          • @AnriëtteMyburgh 您可以还原还原提交,以便稍后将它们合并到您实际上无法使用“merge -s ours”策略轻松做到的事情。
          • 谢谢,这正是我所需要的,在一个特性分支中有一些我不想在 master 中进行的较旧的提交,以及我在 master 中确实想要的一堆。干净整洁。
          • 谢谢,这种方式更好恕我直言,在进行还原后,您可以看到所有未合并的提交的清晰日志,更容易遵循和取消还原
          • 这对我来说比以前的答案更好
          【解决方案7】:

          提交包括祖先。如果不合并先前的提交,则无法合并提交。

          当然,您可以挑选它们。当您有一个处于维护模式的分支时,这是一个很好的流程。

          【讨论】:

          • 谢谢,樱桃采摘可以完成这项工作。没有我希望的那么好,但它会做到的。
          【解决方案8】:

          在 master10 中为您想要的更改创建第三个分支,而不是在 master20 中。始终将 master10 视为您的“主人”,这是所有分支中最稳定的。所有其他分支都希望始终保持同步的分支。

          【讨论】:

          • 我想这可能行得通,但我已经让自己进入这种状态,第三个分支可能会让我更加困惑。 :)
          猜你喜欢
          • 1970-01-01
          • 2018-10-17
          • 2019-10-17
          • 2021-04-02
          • 2011-11-06
          • 1970-01-01
          • 1970-01-01
          • 2018-03-11
          相关资源
          最近更新 更多