【发布时间】:2019-11-25 11:29:25
【问题描述】:
我必须在 git 存储库中重写非常旧的提交,并且不确定它是否可能。重写我的意思是压缩和改写一些提交。还值得一提的是,存储库中有很多合并提交,其中大部分应该保留。
假设我的仓库是A <- B <- C <- D <- E <- ... X <- Y <- Z,我必须压缩A 和B 并改写C 和D。
好吧,我创建了一个新分支tmp,并做了以下事情:
- 我的
tmp分支引用了D提交。 - 我为所需的提交做了一个 squash 和 reword。
- 现在在
tmp分支中,我有这样的东西-A' <- C' <- D'。顺便说一句,rebase 忽略D之前的所有合并提交实际上很好,但D之后的合并提交必须保留。
现在我想以某种方式合并我的tmp 分支和master 分支以获得如下内容:A' <- C' <- D' <- E <- ... <- X <- Y <- Z,所有合并提交都从E 开始。对我来说,这看起来像是更改提交 E 的父级,但不确定是否可以这样做。可能还有其他一些方法可以实现我的需要。
更新
我试图在master 分支上创建一个git replace D D',在此之后git filter-branch -- tmp 几乎可以工作。不幸的是,当我在D 移到底部之后执行替换一些命令时,历史看起来像A <- E <- F <- A' <- C' <- D' <- G <- ... <- X <- Y <- Z,这对我来说很奇怪,但是当我尝试git replace C D' 时,一切正常,除了重复D 和@987654345 @提交。不确定这是否是一种好方法,但在我看来,这是唯一一种。
抱歉,如果有什么不清楚的地方,我会尽力澄清。
【问题讨论】:
-
"对我来说,这看起来像是为提交
E更改父级:这永远不会发生。如果它的父级更改,它将不再是E,而是另一个提交E'。 每一次提交都必须改变历史以反映新的祖先。您可以在filter-branch周围进行一些搜索,但请注意,这是相当繁重的,甚至更多(和旧的)提交。 -
我猜你可以一直到
A进行交互式变基。但正如@RomainValeri 提到的,这也会改变每次提交。 -
@mnestorov,是的,但是有很多提交,此外,我必须保存一些合并提交,但是据我所知,使用 rebase 很难做到。
-
@RomainValeri 谢谢,我会的。
-
filter-branch是正确的工具。与上面的 cmets 不同,这不是一个特别繁重的操作——即使对于大型历史,git 也可以非常有效地处理这个问题。然而,它是一个重大的历史重写,这对团队来说是有成本的。
标签: git git-rebase git-rewrite-history