Github:可以合并(rebase)从PR修改基本分支吗?

时间:2017-10-04 23:06:48

标签: git github

问题是数据库迁移刚刚合并到master分支。出于性能原因,我们不能告诉我们生产中的迁移。迁移脚本不能保留在历史记录中,因为它将被应用。

但是,如果我适当地修改了迁移脚本,那么它将在该点之后中断所有提交。直到应用所有修复的新提交。但这会在历史上留下一堆破碎的提交。

我想回到十几个提交中,一次一个地用一个单独的修复程序对它们进行交互式修改,然后将其余的历史应用到顶部。我真正的问题是,这可以通过拉取请求来完成吗?

这个问题是GitHub特有的,因为我听说它的rebase与标准git rebase略有不同。假设我有这个:

            E   F
            o---o
           /    ^ feature
A   B   C / D
o---o---o---o
            ^ master

如果我将feature重新定义到master就可以了(即使用Rebase合并PR):

A   B   C   D   E'  F'
o---o---o---o---o---o
                    ^ master
                    ^ feature

然而,当我在feature分支上提交比旧共同祖先(B保留迁移,C已删除,D依赖的提交时会发生什么情况关于迁移的变化):

    B'  D'  E   F
    o---o---o---o
   /            ^ feature
A / B   C   D
o---o---o---o
            ^ master

feature合并到master时,是否会这样做?

A   B   C   D   B'  D'  E   F
o---o---o---o---o---o---o---o
                            ^ master
                            ^ feature

有效地保持不良移民,毫无疑问会造成一些可怕的冲突。我想有这个:

A   B'  D'  E   F
o---o---o---o---o
                ^ master
                ^ feature

或者是我唯一的解决方案来重新定位master分支(小心)并强制推回它?

2 个答案:

答案 0 :(得分:0)

对于你的标题问题,没有拉请求不能变基。

对于您的根本问题,我建议您使用git revertdocs)。它将创建一个新的提交,撤消原始的指定提交所做的一切。

例如,如果您通过提交123abc添加了不受欢迎的迁移,则可以运行

git revert 123abc

将有效地创建一个新的提交ctrl + z-ing在commit 123abc中所做的所有更改。

答案 1 :(得分:0)

首先,让我们看看问题:

  

可以合并(rebase)修改[pull request]的基本分支吗?

没有。好吧,我们需要更精确;让我们回过头来看看。但就我的意思而言,这只是“不”。

  

我想回到十几个提交中,一次一个地用一个单独的修复程序对它们进行交互式修改,然后将其余的历史应用到顶部。我真正的问题是,这可以通过拉取请求来完成吗?

没有

GitHub喜欢掩盖Git的细节(好吧,就像任何计算机或网站都可以说有喜欢,不喜欢和感受 1 ),但是有一些绝对的保证,包括这一个关键项目:没有提交任何更改。

鉴于没有提交更改,我们如何设法删除错误提交或重写历史记录?就此而言,git commit --amend 做什么似乎正在改变提交?答案在你的图表中(所以你可能已经知道了):我们可以复制提交,通过提取原始提交,在Git具有的可写区域(索引和/或工作)中进行一些更改-tree),并使 new 提交“与原件一样好”,但它们是新的和改进的。当然,与原始版本不同,因此它们具有不同的“真实名称”:不同的哈希ID。

我们假装改变历史的方式是我们 - 我们所有人,无论是Git用户还是运行Git命令的计算机 - 都相互同意某种程度的疯狂和/或失明,为了找到一些提交,我们都从一个名称开始,如masterfeaturerumpelstiltskin/evil_or_misunderstood。我们将该名称转换为哈希ID,并使用它来查找我们的提交。而且这些名称是可以更改的:如果我们在一系列新提交的顶部打了一个名字,并忘记它曾经是一系列旧的提交,那么为什么呢,它就像一样我们改变了历史!

当您使用各种GitHub clicky按钮合并内容时,您会得到:

  • 真正合并(git merge --no-ff)或
  • “壁球”(git merge --squash)或
  • a git rebase后跟git merge --ff-only,并应用了一些安全检查。

为了真正理解这些,我们还必须查看内部和GitHub中的pull请求是如何工作的,但为了简单起见,我们可以将其视为:一个pull请求会发送你没有的任何提交,进入他们的存储库,以便他们可以运行上述命令。实际情况就是如此,虽然我认为GitHub有时会使用Git的内部“替代”来玩各种技巧,以避免复制对象。

在任何情况下,所有他们必须在这里工作的是你给他们的提交,这是无法修改的。他们可以复制它们(git rebase),它们通过一些有限的更改复制它们(GitHub的保护机制基本上使得在任何复制步骤中没有合并冲突,并且在rebase之后没有比它们已经完成合并)或进行一次新的提交:真正的合并提交或压缩提交。

最终结果将是他们的分支名称将指向一些新的提交,这将指向一些先前的提交,这将最终返回到他们的旧分支提示,并且没有任何内部提交将与原始拉取请求中的任何重要方式都有所不同。此外,他们的旧分支提示 - 您标记为D - 的提交将位于最终链中:

A   B   C   D
o---o---o---o-...-o  <-- master

无论图片在...部分之后的位置如何,之前的部分 ... - 从D开始并向后工作到{{1} } - 将完全不变。

  

我想有这个:

A

要重新编写历史记录,通常必须强制推送。你必须说服一个Git实例 - 在这种情况下,一个在GitHub上 - 将A B' D' E F o---o---o---o---o 移回master。一旦发生这种情况,然后就可以向链中添加新的提交,例如A等。但是这种倒带和重新生成并不是Git“喜欢”(再次参见脚注1)要做的事情:必须使用B'git push -f强制它。

1 不要拟人化计算机;他们讨厌那个。