- 检出两个分支的提交父级
- 创建和检出临时分支
- 手动挑选所有提交
- 将有问题的重建分支重置为指向临时分支
最简单的方法是在reflog中找到重置开始前分支的最新提交...
git reflog
并将当前分支重置为它(在使用--hard
选项进行重置之前,请务必确保绝对确定)。
假设旧提交记录在引用日志中为HEAD@{2}
:
git reset --hard HEAD@{2}
git reset --hard "HEAD@{2}"
您可以通过执行 git log HEAD@{2}
(Windows:git log "HEAD@{2}"
)来查看候选老头的历史。
如果您没有禁用分支引用日志,您应该可以简单地执行 git reflog branchname@{1}
,因为在重新基于之前会将分支头分离,然后再附加到最终头上。不过,请再次确认此行为,因为我最近没有验证过。
默认情况下,对于非裸仓库,所有引用日志都是激活的:
[core]
logAllRefUpdates = true
git log -g
获得更好的格式化输出(来自Scott Chacon的http://progit.org/book中的提示)。 - karmigit rebase -i --abort
才行,仅以上面提到的操作不足以解决问题。 - Hazokgit rebase --abort
(使用-i
选项与--abort
一起使用没有意义)是用于放弃未完成的变基操作,可能是因为出现了冲突,也可能是因为它是交互式的,或者两者都有;这不是关于撤消成功的变基操作,这正是问题所在。根据你的情况,你应该使用rebase --abort
或reset --hard
,不需要同时使用两个命令。 - CB Baileygit tag BACKUP
。如果出了问题,可以返回备份:git reset --hard BACKUP
。 - kolyptocommit:
为前缀,而不是 rebase:
。听起来很明显,但我曾经被这个搞糊涂了一会儿。 - Warpling实际上,rebase 会将你的起点保存到 ORIG_HEAD
中,所以这通常很简单:
Actually, rebase saves your starting point to ORIG_HEAD
so this is usually as simple as:
git reset --hard ORIG_HEAD
然而,reset
、rebase
以及merge
命令都会将你的原始HEAD
指针保存到ORIG_HEAD
中。因此,如果自重新设置后你执行了这些命令中的任何一个,那么你必须使用引用日志才能撤销你尝试撤销的变基操作。
ORIG_HEAD
不再有用,你也可以使用branchName@{n}
语法,其中n
是分支指针的第n个先前位置。例如,如果你将featureA
分支变基到master
分支,但是你不喜欢变基的结果,那么你可以简单地执行git reset --hard featureA@{1}
将分支重置回在变基之前的确切位置。你可以在官方Git修订文档中了解更多关于branch@{n}
语法的内容。 - user456814git rebase --abort
。 - Sephgit rebase --abort
? - UpTheCreekgit status
命令,看看它是否提到了变基操作。无论如何,执行 git rebase --abort
命令应该是无害的。如果没有正在进行的变基操作,它只会抱怨 "fatal: No rebase in progress?
"。 - Jacopo TedeschiCharles的回答有效,但您可能希望这样做:
git rebase --abort
要在reset
之后进行清理。
否则,您可能会收到“Interactive rebase already started
”的消息。
reflog
和reset --hard
之后,你可能仍需要中止rebase以使其恢复正常。 - mattmc3将该分支重置为其旧提示的悬挂提交对象当然是最好的解决方案,因为它可以在不费力气的情况下恢复先前的状态。但是如果您不小心丢失了这些提交(例如,因为您在此期间清理了您的存储库,或者这是一个新克隆),则始终可以再次将分支变基。关键是使用--onto
开关。
假设您有一个名为topic
的主题分支,您在master
提示为0deadbeef
提交时从中分支出来。在topic
分支上的某个时刻,您执行了git rebase master
。现在您想撤消此操作。以下是如何完成的:
git rebase --onto 0deadbeef master topic
这将获取位于topic
上但不在master
上的所有提交,并将它们重放到0deadbeef
之上。
使用--onto
选项,您可以将自己的历史记录重新排列成几乎任何形状。
玩得开心。:-)
如果您将分支推送到远程存储库(通常是 origin),然后成功地进行了变基(不合并)(git rebase --abort
会显示 "No rebase in progress"),则可以使用以下命令轻松重置分支:
git reset --hard origin/{branchName}
例如:
$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is ahead of 'origin/{branchName}' by 135 commits.
(use "git push" to publish your local commits)
nothing to commit, working directory clean
$ ~/work/projects/{ProjectName} $ git reset --hard origin/{branchName}
HEAD is now at 6df5719 "Commit message".
$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is up-to-date with 'origin/{branchName}.
nothing to commit, working directory clean
git reset --hard origin/{branchName}
这是通过重新设置基准线重置所有本地更改的正确解决方案。
在进行任何非微不足道的操作之前,我会在分支上打上一个备份标签(大多数rebase是微不足道的操作,但如果看起来有任何复杂性,我会这样做)。
然后,恢复备份很容易,只需运行命令git reset --hard BACKUP
即可。
branchName@{n}
的语法,这里的n
代表该分支指针向前第n个位置。例如,如果你将featureA
分支变基到master
分支上,但不喜欢变基的结果,那么你只需运行git reset --hard featureA@{1}
将分支重置回进行变基之前的状态。你可以在Git修订官方文档中了解更多有关branch@{n}
语法的信息。 - user456814reflog
对我没用。
对我有用的是类似于这里描述的方法。在.git/logs/refs中打开以被rebase的分支命名的文件,并找到包含"rebase finished"的行,类似于:
5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000 rebase finished: refs/heads/integrate onto 9e460878
git checkout 88552c8f
git log
git checkout -b lost_changes
rebase(finish):
后跟着3个提交ID。第二个ID是正确的。 - PatPatchPatrick对于多个提交(commit),请记住任何一个提交都引用了指向该提交的所有历史记录。因此,在查尔斯(Charles)的答案中,将“旧提交”解读为“旧提交中最新的提交”。如果您重置到该提交,那么该提交之前的所有历史记录将重新出现。这应该可以实现你想要的效果。
commit:
是你想要重置到HEAD@{#}的内容。不是rebase:
、reset:
、merge:
或checkout:
。 - cachius