【问题标题】:Force branch to be rebased before it is merged and pushed在合并和推送之前强制分支重新定位
【发布时间】:2019-07-11 19:47:51
【问题描述】:

我想在我的 Gitlab 服务器上添加一个钩子,以防止将合并的分支推送到 master 上,如果它们之前没有 rebase 的话。

例如: A---B---C---D ← master \ E---F---G ← new-feature

我希望用户在合并/推送之前重新调整他的功能。 A---B---C---D-------------H ← master \ / E'---F'---G'

我不希望这个被推送 A---B---C---D---H ← master \ / E---F---G

这是一个好的开始,但我不认为只拒绝非空的合并提交: Force Feature Branch to be Rebased Before it is Merged or Pushed

【问题讨论】:

    标签: git gitlab


    【解决方案1】:

    如果你还在寻找这个。 gitlab 是唯一实现此功能的 git 服务器。他们称之为半线性历史。 看第二个选项

    这将在您的合并请求中无缝地强制执行这种历史记录(看右边):

    【讨论】:

    • 谢谢,我会在更新 Gitlab CE 实例时看看这个功能
    【解决方案2】:

    绝对有可能,但是你需要写一些代码。您还必须确定精确定义“好的”提交图更新的内容。你的例子说一个请求来自这个:

    o--o--o--*   <-- master
    

    到这里:

    o--o--o--*---o   <-- master
        \       /
         o--o--o
    

    将被拒绝,而这个:

    o--o--o--*---------o   <-- master
              \       /
               o--o--o
    

    将被接受。但是第三种选择呢:

    o--o--o--*------o-----o   <-- master
              \    /     /
               o--o--o--o
    

    这增加了两个合并,而不仅仅是一个;但没有 new 提交的合并有任何父级是 master 先前值的祖先。

    那么,这个呢?

    o--o--o   <-- master
    

    (这里的推送删除了曾经是master的提示的提交。)

    如果第二次推送,即添加了两次合并,但它们都没有返回到任何较早的提交,被接受,并且最后一次推送也不被接受要被接受,您的任务的一部分很容易:您希望最多允许一个合并,也许将其限制为恰好两个父级及其两个父级之一——也许这甚至必须是“第一个父级”——作为先验值master(标记为 * 的提交)。您剩下的任务可能是完全允许 ​​no 合并,只要提议的新 master 不是旧 master 的祖先(不会删除任何提交)。

    如果第二个(两次合并)推送被接受,编码会比较棘手。请注意,如果不被接受,有人仍然可以推送这样的合并,他们只需分多个步骤进行(每次合并一次推送)。

    【讨论】:

      【解决方案3】:

      强制变基的通常原因是对合并提交的病态仇恨,因为设置策略的人看不到它们的价值。目前尚不清楚为什么要利用 rebase 的缺点(可能是中间提交不会经过测试)但仍然有合并;在我看来,这似乎是最不有价值的合并提交。但如果你必须...

      您暗示您要接受的合并将是“空的”;这并不完全正确。它将更改应用到它的第一个父级(尽管不是它的第二个父级,因为如果允许的话,这将是一个快进)。

      我认为您真正要说的是,如果第一个父级可从第二个父级访问(通过父级指针),您将接受合并。所以你可以获取

      的输出
      git rev-list --merges $oldrev..$newrev
      

      并将每个生成的提交 ID 作为 commit-ID 参数输入

      git merge-base --is-ancestor commit-ID^ commit-ID^2
      

      如果merge-base 命令返回非零,则拒绝。

      (从技术上讲,我猜您可能还想确保提交没有 3 个或更多父项。)

      这仍然允许这样的事情

           (origin/master)
                  |
      x -- x -- x -------------------- M <--(master)
                 \                    /
                  x -- x -------x -- x
                        \      /
                         x -- x
      

      如果避免这是一条规则,那就更难了;您基本上希望每个合并都可以通过头部提交的第一父指针访问。 (但你不能只是说应该可以从头部提交的第一个父级访问合并,因为那样你仍然允许

           (origin/master)
                  |
      x -- x -- x -------------------- M -- x<--(master)
                 \                    /
                  x -- x -------x -- x
                        \      /
                         x -- x
      

      这是同一件事。)因此,作为开始寻找合并之前的“第一步”,您可以做一个

      git rev-list --first-parent $oldrev..$newrev
      

      并挂在返回的所有提交 ID 值的列表上,这样当您找到每个合并时,您可以确认它在该列表中。

      如果这一切听起来一点都不好玩,我完全同意;这就是为什么我不会费心尝试根据这个建议组装一个工作脚本的原因,以及为什么我建议你要么允许合并,要么不这样做,而不是尝试采取这种不寻常的中间立场。

      【讨论】:

      • 感谢您的详细解答。一个 rebase 功能分支将使用 master 的最后更改进行测试。我接受快进合并,但有时保留分支的绘图很有趣。
      • 一个变基特性分支的最后一次提交已经被测试过了。中间提交,不太可能。除非您从现在重新建立的分支测试并修复每个 prior 提交,否则您最终可能会得到 x--x--O--x--O--x--x--x--O 的历史记录,其中 x 可能无法正常构建或运行,如果你曾经想使用bisect 来追踪缺陷。
      • 这是一个很好的演示,实际上是的,你需要测试,最终在 rebase 之后修复所有先前的提交。
      • @mark:当您强制与 no-ff 合并时,您可以保持集成分支清洁任何“检查点提交”,因为您可以使用第一个父日志跟踪交付,然后您可以从那里平分仅限第一父母(见stackoverflow.com/questions/5638211/…)并找到有罪的合并
      • 找到有罪的合并后,您离发现错误还很近,就好像您能够将有罪的提交一分为二一样。
      猜你喜欢
      • 2012-07-12
      • 2020-10-22
      • 1970-01-01
      • 1970-01-01
      • 2012-08-23
      • 1970-01-01
      • 1970-01-01
      • 2022-11-16
      • 1970-01-01
      相关资源
      最近更新 更多