我们有一个主分支,我们已经合并了10个功能分支,一次一个。
所以最近的历史看起来像这样:
merged feat/10 (HEAD of master)
merged feat/9
merged feat/8
merged feat/7
merged feat/6
merged feat/5
...
现在我们发现feat/7
很糟糕,我们想把它从主人那里拿走。恢复合并提交是不够的,因为我们根本不希望破坏的提交存在于我们的历史记录中。我们无法真正使用交互式rebase,因为这会使历史变得平坦,使其看起来好像完全在一个分支上完成,并且我们希望保留所有良好合并历史记录。
有没有办法从分支机构的历史记录中删除特定的合并提交?
我会注意到真实的历史要比你在上面的例子中看到的要复杂得多,所以手动重做所有的合并,因为feat / 7不是一个好的选择。
修改
为了澄清那些投票将其作为一个副本关闭的人:这不是关于如何使用rebase进行提交的常见问题解答,当然这已被多次回答。这里的问题是关于提交而不展平合并历史记录。
答案 0 :(得分:1)
如果你的历史记录目前看起来那样并且你没有删除分支,那么你可以简单地git reset --hard HEAD~4
这将在7合并之前将代码重置回状态然后你只需git merge
好的分支回来。这是我能想到的最简单的方式。
编辑: 您可以在rebase上使用-p开关来保留合并,但将此开关与-i一起使用可能会产生结果。检查man git-rebase页面并查看BUGS部分以查看当前的错误。
EDIT2:如果在使用此命令之前未采取适当的预防措施,我不承担任何责任。在阅读联机帮助页之前不要使用它。
答案 1 :(得分:1)
您可以使用git filter-branch --parent-filter
重写feat/8
提交,以便其父级指向feat/6
提交。保留所有其他提交的父级(9-10),这应该保留历史中的合并提交。
唯一的问题是导致删除代码的冲突会发生什么变化......没有真正的知道方式,而且可能是罪魁祸首。
答案 2 :(得分:1)
这不是你想要做的事情(可以说是“删除”合并提交),但实际上比在git reset --hard
之后让你的协作者说服rebase
更容易或filter-branch
。只需还原合并。
git revert -m 1 <commit_for_feat7>
我并不特别喜欢使用恢复来污染我的主分支,但它没有任何内在错误。如果你不打算暂时修补feat7
,或者只是想让它的变更集超出历史,那么这个解决方案比历史修订要少得多。
答案 3 :(得分:0)
你不能只是从git中删除东西,因为当前的哈希值取决于整个历史记录。
一个选项是创建一个从feat / 6开始的新分支,然后从feat / 8开始合并,以便分支头可以指向不同的哈希,而不需要更改feat / 7。
另一种选择,如果我没记错的话,是git replace
(我认为以前称之为移植物)。它可以让你将feat / 8处的指针从feat / 7“替换”为feat / 6。我不完全确定它是如何实现这一点的,但看起来它不是真正的替代品,因为feat / 8仍然有一个指向某个地方的壮举/ 7,因为哈希不会改变,但是{{1}以某种方式添加一个备用历史记录,其中feat / 8指向feat / 6。
来自man page:
git replace
在.git / refs / replace /
中添加替换引用替换引用的名称是对象的SHA1 更换。替换引用的内容是SHA1的SHA1 替换对象。
除非给出-f,否则替换引用必须不存在 .git / refs / replace / directory。
所有git命令都默认使用替换引用 除了那些进行可达性遍历(修剪,包转移和 fsck的)。
可以禁用任何替换引用的使用 在git之后使用--no-replace-objects选项命令。
编辑:第二个想法git replace [-f] <object> <replacement>
git replace -d <object>…
git replace -l [<pattern>]
可能是一个坏主意,因为在feat / 8的合并中将存在来自feat / 7的更改。你可能应该选择第一个选项:从合并的专长/ 6开始一个新的分支,然后从专长/ 8开始重新开始