执行git rebase -i时commit消失是否正常?如何恢复仓库状态
现象合理性说明
这个现象是完全符合Git交互式rebase运行规则的正常表现,不存在功能异常:
- 交互式rebase的待办列表默认按提交时间从旧到新从上到下排列,
squash(缩写s)指令的作用是将当前行的提交,合并到它上方紧邻的、状态为pick(缩写p)的前置提交中。第一次编辑待办时把s hash 1放在列表最顶部,该行上方没有可作为合并目标的pick状态提交,Git会直接抛出操作错误。 - 执行
git rebase --edit-todo修改待办时,Git会自动过滤掉当前上下文里无效、无法执行的条目,因此看不到原本写入的p hash 2行。此时仅保留p hash 1就执行git rebase --continue,相当于告知Git本次rebase只需要应用commit 1,commit 2没有被加入待办执行队列,自然不会出现在rebase完成后的提交历史里,不属于异常丢失。
恢复到rebase前状态的方法
有两种可靠的恢复方式,按操作简便度排序:
- 如果当前rebase进程还未正常结束(即执行完continue后没有主动执行过其他终止rebase的操作),直接执行以下命令即可一键终止rebase,回到操作前的状态:
git rebase --abort - 如果rebase进程已经结束,或上述命令执行无效,可以通过Git操作日志恢复:
- 首先执行
git reflog查看本地仓库所有HEAD指针的变更记录,列表中会存在执行git rebase -i HEAD~2之前的HEAD条目,每条记录前带有HEAD@{数字}格式的标识,对应记录的备注就是rebase前最新的提交(提交信息为"2"的条目)。 - 确认对应条目后,执行以下命令(将
{n}替换为查到的对应数字),即可将仓库完全回退到rebase执行前的状态,此前“消失”的第二个提交会完整恢复:git reset --hard HEAD@{n}
- 首先执行
Git在执行rebase、reset、merge这类会改写提交历史的操作前,都会自动将操作前的指针状态存入reflog,只要没有手动执行reflog过期清理,哪怕提交不在当前分支的历史链路中,也能通过reflog找回,不会真的永久丢失。
内容的提问来源于stack exchange,提问作者yakou tsuchimikado
相关产品推荐
相关产品推荐

