我修改而不是解决交互式变基中的冲突。我可以撤消吗?
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
的内容正是您想要的最终结果,您只是缺少 D
和 E
提交。
你能做的是:
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
现在将向您显示 C
和 F
之间的完整差异。
现在你用你最喜欢的add/commit工具(我喜欢git gui
),挑出每一个原本属于D
的改动,然后提交。重复 E
。在那之后,只有 F
的变化存在;您可以一次添加并提交它们。当然,如果 E
和 F
之间还有更多,您将不得不冲洗并重复。
这样做的好处是您实际上不需要更改任何内容。最终结果将完全是 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
。您可以使新的分支或标记名称指向原始提交,然后使用 name
、name~1
、name~2
等返回原始提交(预变基)提交:
git tag oops ORIG_HEAD
现在 oops
是提交 F
,oops~1
是 E
,依此类推。
您可以git show
任何提交,git checkout <commit-id> -- <path>
从中获取文件,git cherry-pick <commit-id>
将该提交作为增量应用到您当前的位置,等等。
我正在做一个大型的交互式 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
的内容正是您想要的最终结果,您只是缺少 D
和 E
提交。
你能做的是:
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
现在将向您显示 C
和 F
之间的完整差异。
现在你用你最喜欢的add/commit工具(我喜欢git gui
),挑出每一个原本属于D
的改动,然后提交。重复 E
。在那之后,只有 F
的变化存在;您可以一次添加并提交它们。当然,如果 E
和 F
之间还有更多,您将不得不冲洗并重复。
这样做的好处是您实际上不需要更改任何内容。最终结果将完全是 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
。您可以使新的分支或标记名称指向原始提交,然后使用 name
、name~1
、name~2
等返回原始提交(预变基)提交:
git tag oops ORIG_HEAD
现在 oops
是提交 F
,oops~1
是 E
,依此类推。
您可以git show
任何提交,git checkout <commit-id> -- <path>
从中获取文件,git cherry-pick <commit-id>
将该提交作为增量应用到您当前的位置,等等。