【发布时间】:2014-02-14 00:25:56
【问题描述】:
我在一个分支上运行了 git rebase 并修复了所有冲突,然后意识到对于这个特定的分支我需要运行 git merge 来保留历史记录。有没有办法“撤消”变基但在运行 git merge 时自动重新应用我的修复?
【问题讨论】:
-
如果您将
rerere.enabled设置为true,那应该已经发生了。
标签: git git-merge git-rebase undo-redo
我在一个分支上运行了 git rebase 并修复了所有冲突,然后意识到对于这个特定的分支我需要运行 git merge 来保留历史记录。有没有办法“撤消”变基但在运行 git merge 时自动重新应用我的修复?
【问题讨论】:
rerere.enabled 设置为true,那应该已经发生了。
标签: git git-merge git-rebase undo-redo
作为Amber said in a comment,如果您打开 rerere,git 将“重新”记录您之前的“重新”解决方案(三个重新中的两个)。然后,如果您将事物重置为预变基状态并“git merge”,它应该“重新”使用它们(最后一个“重新”)。
但如果没有,就不会。
那该怎么办?假设您对自己的解决方案非常有信心 :-) 您可以试试这个。
ORIG_HEAD 可能仍指向原始提交链(预变基)。如果没有,请在 reflogs 中找到旧的分支提示。给它一个标签(分支或标签名称),同时在后变基链上保留一个标签。也就是我们要复活旧的枝尖,也要保留新的枝尖。 (确切的为什么在你理解了其余部分之后应该是显而易见的。)
我假设在 rebase 时,您修改了提交 C 和 F 并完全删除了 D 和 E,因为不再需要。并不是说这真的很重要。 F' 是唯一关键的提交。关键是提交F' 捕获了工作树的“最终、全部解决”版本:
C - D - E - F <-- feature_orig
/
A - B - G - H - I - J <-- mainline
\
C' - F' <-- feature
以上是您在执行git branch feature_orig ORIG_HEAD 之后可以看到的内容(或从 reflogs 中恢复原始提示并使用它来创建 feature_orig)。
您现在(根据原始问题)想要的是合并:“将功能合并到主线”或“将主线合并到功能”。除了,您希望它发生在/与feature_orig 上,而不是重新定位的feature。
还有一个问题:你想保留feature 分支吗? (如果你在这里将 mainline 合并到 feature 中,你可能会这样做。如果将功能合并到主线中,可能不会。但至多,我怀疑你会想要保留 feature_orig,而不是重新定位的线。)让我们现在再移动一个分支名称,以——我希望——使画面更清晰:
$ git branch -m feature feature_rebased
现在我们有了这个:
C - D - E - F <-- feature_orig
/
A - B - G - H - I - J <-- mainline
\
C' - F' <-- feature_rebased
现在进行合并。进入您希望合并提交显示的分支:
$ git checkout ...
(我不知道这是哪个分支,feature_orig 或 mainline!)
然后进行合并,忽略结果而不提交:
$ git merge --no-commit ...
(无论您要合并哪个分支)。
现在只需将每个文件替换为来自提交 F' 的版本(注意,我假设您在此处的顶级工作目录中):
$ git rm -rf .; git checkout feature_rebased -- .
rm 步骤完全清空索引,包括所有冲突以及工作树。然后checkout 步骤使用提交F' 中的任何内容(通过分支名称feature_rebased 获得)完全重新填充索引和工作树。
您现在可以在您所在的任何分支上提交合并。具体来说,假设您在 feature_orig 上并要求 git 合并 mainline。在git commit 之后,您应该将其作为您的提交图:
C - D - E - F - M <-- feature_orig
/ /
A - B - G - H - I - J <-- mainline
\
C' - F' <-- feature_rebased
我认为这里值得一提的是,这只是提交图。 tree 的内容——当你git checkout 任何这些提交时你在你的工作目录中获得的文件——由提交时索引/暂存区域的内容决定已创建。
这就是为什么我们可以git rm 一切,然后git checkout <em>id</em> -- . 来设置合并提交的内容。当我们提交合并时,我们所做的就是创建一个提交M,其父级是F 和J,其内容是“索引中现在的任何内容”。
(父F和J的顺序,以及新提交ID写入哪个分支名称,由我们开始和结束时所在的分支决定git merge 进程。如果我们“在分支feature_orig 上,那么F 是第一个父级,M 转到“在分支feature_orig”上。如果我们在“在分支mainline 上,那么J是第一个父母,M 转到“分支mainline”。当然,准备好的提交文本,你可以在提交发生之前编辑,有点不同。但是你可以编辑它来阅读你的任何内容喜欢。)
此时(或者甚至更早)您现在可以将 feature_orig 重命名为 feature,如果您想保留该名称。您也可以删除分支feature_rebased,因为不再需要保存提交C' 和F'。事实上,我们只是真的想坚持F',以便我们可以git checkout 它的树——我们可以在完成checkout 后立即删除分支。
【讨论】: