3

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

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

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

Git 树示例:

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

变基后:A-B-C-F(C 现在修改了 D 和 E 的变化)

4

3 回答 3

3

您所做的每一个提交,无论是否修改,仍然“在那里”,并且它们都可以通过 reflogs 找到。这是因为实际上git commit --amend 并没有改变任何东西,它只是做了一个的提交,“把旧的推到一边”,就像它一样。

当然,您没有进行的提交(即,如果索引中存在冲突状态以致git commit拒绝提交),当然不会被保存。

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

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

git tag oops ORIG_HEAD

现在oops是 commit Foops~1is E,等等。

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

于 2017-01-03T09:08:46.450 回答
3

是的你可以。

通常,我会马上回去重做所有事情,但我可以理解这个问题 - 听起来你已经在 rebase 上投入了大量时间,所以似乎不再需要重新做所有这些事情。

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

你可以做的是:

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

现在您使用您最喜欢的添加/提交工具(我喜欢git gui)并挑选出D最初属于的所有更改,然后提交。重复E。在那之后,只有从F那里发生的变化;您可以一次性添加和提交它们。当然,如果之间有更多EF您将不得不冲洗并重复。

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

于 2017-01-03T08:56:15.113 回答
2

在重新定位/修改提交之后,原始提交仍然存在。虽然如果它不能通过分支到达,它不会出现在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

于 2017-01-03T09:07:44.037 回答