- 检出两个分支的提交父级
- 创建和检出临时分支
- 手动挑选所有提交
- 将有问题的重建分支重置为指向临时分支
如果你不想进行硬重置...
您可以从reflog中检出提交,然后将其保存为新分支:
git reflog
找到在你开始变基之前的提交。您可能需要向下滚动以查找它(按Enter或PageDown键)。注意HEAD号并替换57:
git checkout HEAD@{57}
审核分支/提交记录,如果正确,则使用此HEAD创建新的分支:
git checkout -b new_branch_name
跟随@Allan和@Zearin的解决方案,我本来想进行评论但是声望不够,所以我使用了以下命令:
不要执行git rebase -i --abort
(注意 -i)而是直接执行git rebase --abort
(不要加上-i参数)。
同时使用-i
和--abort
会导致Git向我展示使用/选项列表。
所以这个解决方案下我的之前和当前的分支状态如下:
matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort
matbhz@myPc /my/project/environment (branch-123)
$
另一种不需要硬重置的方法是使用您所需的起始点创建新分支。
与其他解决方案一样,您可以使用reflog查找正确的起始点。
git reflog
你还可以在此处使用git log -g
以获取更多详细信息。
然后,你需要注意到提交SHA(例如:e86a52b851e
)的引用。
最后,你需要使用git branch命令。
git branch recover-branch e86a52b851e
参考文献:https://git-scm.com/book/zh/v2/Git-内部原理维护及数据恢复#_data_recovery
git reset --hard @{1}
不只是 git reflog
命令可以得到 HEAD 的参考日志,每个分支都有自己的参考日志(通过 git reflog <branch>
)。因此,如果你在 master
分支上,则 git reflog master
将列出该分支的所有更改。您可以使用 master@{1}
、master@{2}
等方式引用这些更改。
git rebase
通常会多次更改 HEAD,但当前分支仅会更新一次。
@{1}
只是对“当前分支”的一个快捷方式,所以如果你在 master
上,它等同于 master@{1}
。
git reset --hard ORIG_HEAD
如果在交互式 rebase
过程中使用了 git reset
,则无法正常工作。
假设我将主分支rebase到我的特性分支,然后我得到了30个新的提交,这些提交导致一些问题。我发现最简单的方法通常是删除有问题的提交。
git rebase -i HEAD~31
对最近的31个提交进行交互式变基(如果您选择了太多提交,也不会有影响)。
只需选取您想要删除的提交,并将它们标记为“d”而不是“pick”。现在,这些提交将被删除,从而撤销变基操作(如果您仅删除重新定位时获取的提交)。
我通常做的是
git reset #commit_hash
重置到我认为rebase没有影响的最后一个提交。
接着执行
git pull
现在,您的分支应该与master完全匹配,而rebase提交不应该出现其中。
现在可以在此分支上挑选提交。
我非常烦恼的是,尽管它应该是可自动化的(至少大部分是),但这些答案中没有一个是完全自动的。我创建了一组别名来尝试解决这个问题:
# Useful commands
#################
# Undo the last rebase
undo-rebase = "! f() { : git reset ; PREV_COMMIT=`git x-rev-before-rebase` && git reset --merge \"$PREV_COMMIT\" \"$@\";}; f"
# See what changed since the last rebase
rdiff = "!f() { : git diff ; git diff `git x-rev-before-rebase` "$@";}; f"
# Helpers
########
# Get the revision before the last rebase started
x-rev-before-rebase = !git reflog --skip=1 -1 \"`git x-start-of-rebase`\" --format=\"%gD\"
# Get the revision that started the rebase
x-start-of-rebase = reflog --grep-reflog '^rebase (start)' -1 --format="%gD"
您应该能够轻松地调整它,以允许任意数量的变基后退(操作参数最棘手的部分),如果您在快速进行多个变基的过程中出了差错,则这可能非常有用。
如果任何提交消息以“rebase(start)”开头,它将感到困惑(请不要这样做)。您可以通过匹配此类正则表达式来使正则表达式更具弹性以改善情况:
--grep-reflog "^rebase (start): checkout "
警告:未经测试(正则表达式可能需要调整)
我还没有这样做的原因是因为我不确定每次 rebase 都始于 checkout。有人能证实一下吗?
[如果你对函数开头的空命令(:
)感到好奇,那是为了为别名设置 bash 自动补全的一种方式]
我尝试了重置和reflog的所有建议,但没有成功。恢复IntelliJ的本地历史记录解决了文件丢失的问题。
如果在 git rebase 中出现问题,例如 git rebase --abort
,而您有未提交的文件,则它们将丢失,并且 git reflog
将无法帮助您。这种情况发生在我身上,您需要在此处打破常规思维方式。如果您像我一样幸运地使用 IntelliJ Webstorm,则可以通过 右键单击->本地历史记录
,无论您在版本控制软件中犯了什么错误,都可以恢复到文件/文件夹的先前状态。始终保持另一个故障转移运行是很好的。
git rebase --abort
中止正在进行的变基操作,它并不会撤销已经完成的变基操作。
同时使用两个版本控制系统并不是一个好主意。虽然Jetbrains软件中有这个功能,但你不应该同时使用两种版本控制系统。最好只学习Git,特别是在Stack Overflow上回答关于Git的问题时。 - dudewad
commit:
是你想要重置到HEAD@{#}的内容。不是rebase:
、reset:
、merge:
或checkout:
。 - cachius