我修改而不是解决交互式变基中的冲突。我可以撤消吗?

I amended instead of resolving conflict in interactive rebase. Can I undo?

我正在做一个大型的交互式 rebase,我正在编辑 8 个提交之类的东西。这是用 git commit --amend 完成的。我的问题是,有一次我遇到了一个我没有注意到的合并冲突,所以我继续天真地修改和 git rebase --continue-ing。显然我现在已经将多个提交修改为一个,并且在完成 rebase 后我的大约 4 个提交都消失了。更改已修改为其他提交。

我有什么方法可以撤消这些修改,或者重新应用已经消失的提交?

当然;一种解决方案是返回并再次进行变基,但我在变基中做了很多编辑,所以我希望不必重新做我所有的工作。我是如何陷入这种困境的是另外一回事。

Git 树示例:

变基前:A-B-C-D-E-F

变基后:A-B-C-F(C 现在对 D 和 E 进行了修改)

是的,你可以。

通常情况下,我会马上回去重做所有事情,但我能理解这个问题 - 听起来你已经在 rebase 上投入了很多时间,所以似乎并不邀请重新做所有事情.

我假设您的示例中 F 的内容正是您想要的最终结果,您只是缺少 DE 提交。

你能做的是:

git checkout C             # "git status" should be empty right now
git checkout F .
git reset .
git add only-changes-from-D ; git commit -m D
git add only-changes-from-E ; git commit -m E
git add -A ; git commit -m F

git checkout F . ; git reset . 使您的工作目录包含 F,但您的 HEAD 仍指向 C,索引中没有任何内容。 git status 现在将向您显示 CF 之间的完整差异。

现在你用你最喜欢的add/commit工具(我喜欢git gui),挑出每一个原本属于D的改动,然后提交。重复 E。在那之后,只有 F 的变化存在;您可以一次添加并提交它们。当然,如果 EF 之间还有更多,您将不得不冲洗并重复。

这样做的好处是您实际上不需要更改任何内容。最终结果将完全是 F,但您将根据需要获得一些中间提交。

rebasing/amending 次提交后,原来的提交还在。尽管如果无法通过分支访问它,它不会出现在 git log.

我认为在 git reflog 的帮助下你可以做你想做的事。

git reflog //identify the hash of the commits you want, look for your commit --amend that you want to undo git checkout B git cherry-pick hash-of-commit-C-as-resolved-during-rebase-but-before-amending git cherry-pick hash-of-commit-C-after-amending-with-D git cherry-pick hash-of-commit-C-after-amending-with-E git cherry-pick F

您所做的每一次提交,无论修改与否,都仍然是 "in there",并且它们都可以通过 reflogs 找到。这是因为 git commit --amend 不会 实际上 改变 任何东西,它只是 new 提交可以说 "shoves the old one aside"。

没有 做出的承诺(即,如果索引中存在冲突状态,因此 git commit 拒绝做出承诺)当然是, 未保存。

使用git reflog(或git reflog HEAD)查找每个提交。您可能希望将它们的原始哈希 ID 保存在一个文件中以供剪切和粘贴,因为命名它们的简单方法 HEAD@{3} 等等都是相对的,并且会不断变化。 (也就是说,每次你调整HEAD,原来的HEAD@{3}现在是HEAD@{4}HEAD@{5},很快HEAD@{7},最后是HEAD@{198},唉!:-))

您还可以使用名称 ORIG_HEAD 立即取回原始链(如果您没有 运行 任何其他命令)。也就是说,当您 运行 git rebase -i 然后进行所有编辑、修改提交等并最终完成时,会发生什么 git rebase 将原始分支提示保存在名字 ORIG_HEAD。您可以使新的分支或标记名称指向原始提交,然后使用 namename~1name~2 等返回原始提交(预变基)提交:

git tag oops ORIG_HEAD

现在 oops 是提交 Foops~1E,依此类推。

您可以git show任何提交,git checkout <commit-id> -- <path>从中获取文件,git cherry-pick <commit-id>将该提交作为增量应用到您当前的位置,等等。