题
有人知道如何轻松撤消 git rebase 吗?
我想到的唯一方法是手动进行:
- git checkout 两个分支的提交父级
- 然后从那里创建一个临时分支
- 手动挑选所有提交
- 将我重新建立基础的分支替换为手动创建的分支
在我目前的情况下,这会起作用,因为我可以轻松地发现两个分支的提交(一个是我的东西,另一个是我同事的东西)。
然而,我的方法给我的印象是次优且容易出错(假设我刚刚用我自己的两个分支进行了重新调整)。
有任何想法吗?
澄清:我说的是变基,在此期间重放了一堆提交。不止一个。
解决方案
最简单的方法是找到分支的头提交,因为它就在 rebase 开始之前 转发日志...
git reflog
并将当前分支重置为它(在使用重置之前要绝对确定的通常警告 --hard
选项)。
假设旧的提交是 HEAD@{5}
在参考日志中:
git reset --hard HEAD@{5}
在 Windows 中,您可能需要引用引用:
git reset --hard "HEAD@{5}"
您只需执行以下操作即可查看候选老头的历史记录 git log HEAD@{5}
(视窗: git log "HEAD@{5}"
).
如果您没有禁用每个分支重新记录,您应该能够简单地执行以下操作 git reflog branchname@{1}
作为变基,在重新连接到最终头之前会分离分支头。我会仔细检查这一点,尽管我最近没有验证这一点。
默认情况下,所有引用日志都会针对非裸存储库激活:
[core]
logAllRefUpdates = true
其他提示
实际上,rebase 将你的起点保存为 ORIG_HEAD
所以这通常很简单:
git reset --hard ORIG_HEAD
但是,那 reset
, rebase
和 merge
全部保存原来的 HEAD
指针指向 ORIG_HEAD
因此,如果您在尝试撤消变基后执行了任何这些命令,那么您将不得不使用引用日志。
查尔斯的答案有效,但你可能想这样做:
git rebase --abort
后清理 reset
.
否则,您可能会收到消息“Interactive rebase already started
”.
git reflog
将向您显示 rebase 之前和之后的所有更改,并允许您找到要重置的正确更改。但令我惊讶的是,还没有人在这里提到另一种超级简单的方法:
变基将旧状态保留为 ORIG_HEAD
, ,因此您可以通过运行以下命令来恢复上次变基:
git reset --hard ORIG_HEAD
将分支重置为其旧提示的悬空提交对象当然是最好的解决方案,因为它无需花费任何精力即可恢复之前的状态。但是如果你碰巧丢失了这些提交(f.ex.因为您同时对存储库进行了垃圾收集,或者这是一个新的克隆),您始终可以再次对分支进行变基。这其中的关键是 --onto
转变。
假设您有一个主题分支,富有想象力地称为 topic
, ,你分支了 master
当尖端 master
是 0deadbeef
犯罪。在某个时刻 topic
分支,你做到了 git rebase master
. 。现在您想要撤消此操作。就是这样:
git rebase --onto 0deadbeef master topic
这将进行所有提交 topic
未开启的 master
并在上面重播它们 0deadbeef
.
和 --onto
, ,你可以将你的历史重新排列成几乎 任何形状.
玩得开心。:-)
实际上,在执行任何重要操作之前,我在分支上放置了一个备份标记(大多数变基都是微不足道的,但如果它看起来很复杂,我会这样做)。
然后,恢复就像 git reset --hard BACKUP
.
以防万一 您已将分支推送到远程存储库 (通常是起源)然后你就完成了成功的变基(没有合并)(git rebase --abort
给出“没有进行中的变基”)你可以轻松地 重置分支 使用命令:
git重置--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 rebase --abort
使用 reflog
不适合我。
对我有用的与描述的类似 这里. 。打开 .git/logs/refs 中以重新设置基址的分支命名的文件,找到包含“rebase finsihed”的行,如下所示:
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
对于多次提交,请记住任何提交都会引用导致该提交的所有历史记录。因此,在查尔斯的回答中,将“旧提交”解读为“旧提交中的最新提交”。如果您重置到该提交,那么导致该提交的所有历史记录都将重新出现。这应该做你想做的。
按照@Allan和@Zearin的解决方案,我希望我可以简单地发表评论,但我没有足够的声誉,所以我使用了以下命令:
而不是做 git rebase -i --abort
(注意 -我)我必须简单地做 git rebase --abort
(没有 这 -我).
两者同时使用 -i
和 --abort
同时使 Git 向我显示用法/选项列表。
所以我以前和当前使用此解决方案的分支状态是:
matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort
matbhz@myPc /my/project/environment (branch-123)
$
如果您成功地针对远程分支重新建立基础但不能 git rebase --abort
您仍然可以采取一些技巧来保存您的工作,并且不必强制推送。假设您当前被错误地重新定位的分支称为 your-branch
并正在追踪 origin/your-branch
git branch -m your-branch-rebased
# 重命名当前分支git checkout origin/your-branch
# 签出已知来源的最新状态git checkout -b your-branch
- 查看
git log your-branch-rebased
, , 相比于git log your-branch
并定义缺少的提交your-branch
git cherry-pick COMMIT_HASH
对于每一次提交your-branch-rebased
- 推动你的改变。请注意,两个当地分支机构与
remote/your-branch
你应该只推your-branch
假设我将 master 重新设置为我的功能分支,并且我收到了 30 个新提交,这些提交破坏了某些内容。我发现通常删除错误的提交是最简单的。
git rebase -i HEAD~31
最后 31 次提交的交互式变基(如果您选择太多也没有什么坏处)。
只需获取您想要删除的提交并用“d”而不是“pick”标记它们即可。现在,提交已被有效删除,从而撤消变基(如果您仅删除变基时刚刚获得的提交)。
如果您在分支机构,您可以使用:
git reset --hard @{1}
不仅有 HEAD 的参考日志(通过 git reflog
),每个分支还有 reflog(通过以下方式获得) git reflog <branch>
)。所以,如果你在 master
然后 git reflog master
将列出该分支的所有更改。您可以通过以下方式参考该更改 master@{1}
, master@{2}
, , ETC。
git rebase
通常会多次更改 HEAD,但当前分支只会更新一次。
@{1}
简单来说就是一个 当前分支的快捷方式, ,所以它等于 master@{1}
如果你在 master
.
git reset --hard ORIG_HEAD
如果你使用的话将不起作用 git reset
在互动过程中 rebase
.
对于新手/任何害怕进行硬重置的人,您可以从引用日志中签出提交,然后将其保存为新分支。
git reflog
找到开始变基之前的提交。您可能需要进一步向下滚动才能找到它(按 Enter 或 PageDown)。记下 HEAD 编号并替换 57:
git checkout HEAD@{57}
检查分支/提交,如果看起来不错,请使用此 HEAD 创建一个新分支:
git checkout -b new_branch_name
git重置--hard origin/{branchName}
是重置通过 rebase 完成的所有本地更改的正确解决方案。
我通常做的是git reset #commit_hash
到我认为 rebase 没有效果的最后一次提交。
然后 git pull
现在,您的分支应该与 master 完全匹配,并且 rebased 提交不应包含在其中。
现在,人们可以挑选该分支上的提交。
如果你在 git rebase 中弄乱了一些东西,例如 git rebase --abort
, ,当您有未提交的文件时,它们将会丢失并且 git reflog
不会有帮助。这发生在我身上,你需要跳出框框思考。如果你像我一样幸运并且使用 IntelliJ Webstorm 那么你可以 right-click->local history
并且无论您使用版本控制软件犯了什么错误,都可以恢复到文件/文件夹的先前状态。再次运行故障保护总是好的。