更新:
根据您更新的问题,我了解到文件删除发生的原因。对我来说,这似乎是一种不寻常的情况组合。最有趣的一点是,与我一开始看到的相比,合并的还原操作更加危险。撤消合并(通过重置以在将其推送之前从历史记录中清除它)是典型的程序,并且可以避免这种问题-如果在推送之前捕获到该问题。但这在此时此地没有太大的帮助。
尽管有澄清,我仍然建议反对您提出的历史编辑,而且我在原始答案中包含了所有与该编辑相关的建议。请记住,如果您以一种编辑来自release
的提交的方式重新定位master
,则release
仍将具有原始提交,您将拥有一个奇怪的、易于产生冲突的分裂历史记录,在某些合并操作上会存在冲突(因为重复提交执行相同的操作)。
如果您想将M1中的所有更改放回历史记录中,可以通过还原W1来完成,这样做会减少许多麻烦,虽然仍可能会出现一些冲突,但这是一个更简单的过程;不会创建上游rebase问题;并且在以后的合并操作中会减少冲突。
听起来您正在考虑编辑发布分支的历史记录。出于短期原因(需要“上游rebase”解析)和长期原因(发布分支将不再记录已发布内容),我建议反对它。当然,我可能误解了您的提议,因此让我们从一个共同的起点开始:
您当前拥有类似于
O
\ \ /
\ x
\ /
A
这段代码中的M1
是将feature
错误地合并到了release
中,W1
撤销了M1
,M2
最终将release
合并到了master
。
据我所知,所有这些都已经被推送了,其中一些反映在您发布版本的历史记录中,并且“问题”提交也已经成为master
共享历史的一部分。因此,如果我是您,我会考虑几乎所有内容都是“铁板钉钉”的。
如果您最终决定使用rebase来“修复”发布分支,则需要考虑两件事:
1)最好从发布分支历史记录中删除M1
和W1
,以便其结果树至少正确反映了您发布的内容。(我意识到最终将重新引入M1
的工作,但这不是您发布的内容。)
2)完成后,您必须使用新的release
引用重新执行M2
合并(创建M2'
),然后将master
和自M2
以来从master
分支出的任何其他分支,都rebase到M2'
。如果这是一个活动的存储库,它可能会很快变得复杂。
这就是为什么我不会这样做的原因。那么您还能做什么呢?
听起来release
的输出看起来应该是正确的,因此我不清楚为什么这会对master
产生任何不良影响,直到您尝试合并feature
为止。毕竟,如果在W1
中删除了一个文件,则该文件必须已经被M1
添加(从release
的角度来看),因此将其应用于master
时通常不会有任何净变化。如果master
出现问题,即使它不包含feature
,也可能需要更多信息以了解原因(以及如何处理它)。
(或者,另一方面,如果在您开始尝试将release
合并到主分支之前,feature
已经被合并到master
中-这可以解释为什么合并看起来很混乱-那么这将需要与我所建议的不同的解决方案。)
但是,根据问题的描述,如果您尚未合并“feature”,那么当您尝试将“feature”合并到“master”时,我会预计git会认为通过“M1”已经应用了添加文件的代码“ A”和“B”(然后在“W1”中进行的后续更改恰好撤消了它,但git并不太关心这一点)。
我猜您需要的是执行与“A”和“B”相同操作的新提交。您可以通过将“feature”变基到“M2”(或更高版本的“master”)来相对轻松地完成此操作。问题是,如果您告诉变基命令“master”是您的上游分支,则它将跳过“A”和“B”(因为这些提交已经包含在“master”中)。因此,您必须强制将上游分支设置为提交“O”。
因此,您可以查找提交“O”的SHA值,或者给其打上标签(例如“feature-root”),然后...
git rebase --onto master feature-root feature
yielding
A'
/
O
\ \ /
\ x
\ /
A
所以
C
和
D
不重要(
gc
最终会回收它们),
A
和
B
(以及
M1
)则保留在历史记录中(避免了最棘手的上游 rebase 问题),只有共享
feature
引用的用户需要担心上游 rebase 恢复。