撤消 git rebase

有人知道如何轻松撤消 git rebase 吗?

想到的唯一方法是手动进行操作:

  • git 签出两个分支的提交父对象
  • 然后从那里创建一个临时分支
  • 手动选择所有提交
  • 用手动创建的分支替换我重新建立基础的分支

在我目前的情况下,这是可行的,因为我可以轻松地发现两个分支的提交(一个是我的东西,另一个是我同事的东西)。

但是,我的方法给我的印象是次优且容易出错(例如,我刚刚使用自己的两个分支进行了重新基准化)。

有任何想法吗?

澄清:我说的是一个重定基础,在此基础上重播了很多提交。不只是一个

答案

最简单的方法是找到分支的头提交,就像在reflog 中重新启动基础之前一样...

git reflog

然后将当前分支重置为该分支(通常的警告是在使用--hard选项进行重置之前必须绝对确定)。

假设参考日志中的旧提交为HEAD@{5}

git reset --hard HEAD@{5}

在 Windows 中,您可能需要引用以下引用:

git reset --hard "HEAD@{5}"

您可以通过执行git log HEAD@{5}Windows: git log "HEAD@{5}" )来检查候选旧头的历史git log "HEAD@{5}"

如果尚未对每个分支引用禁用禁用,则应该可以简单地执行git reflog branchname@{1}因为在重新附加到最终头之前,rebase 会分离分支头。我会再次检查,尽管最近还没有验证。

默认情况下,针对非裸存储库激活所有引用日志:

[core]
    logAllRefUpdates = true

实际上,重新设置基准会将您的起点保存到ORIG_HEAD因此通常很简单:

git reset --hard ORIG_HEAD

但是, resetrebasemerge都将原始HEAD指针保存到ORIG_HEAD因此,如果自从 rebase 以来已经执行了其中的任何命令,则尝试撤消操作,则必须使用 reflog。

查尔斯的答案有效,但您可能需要这样做:

git rebase --abort

reset后清理。

否则,您可能会收到消息 “ Interactive rebase already started ”。

将分支重置为其旧提示的悬挂提交对象当然是最好的解决方案,因为它无需花费任何精力即可恢复先前的状态。但是,如果您恰巧丢失了这些提交(例如,因为在此期间您对存储库进行了垃圾回收,或者这是一个新的克隆),则始终可以重新建立分支的基础。关键是--onto开关。

比方说,你有一个特性分支想象力称为topic ,你分出master时的尖master0deadbeef提交。在topic分支上的某个时刻,您做了git rebase master 。现在您要撤消此操作。就是这样:

git rebase --onto 0deadbeef master topic

这将接受不在master上的所有topic提交,并在0deadbeef之上重播它们。

使用--onto ,您可以将您的历史重新排列成几乎任何形状

玩得开心。 :-)

实际上,在执行任何无关紧要的操作之前,我实际上在分支上放置了一个备份标签(大多数 rebase 都是无关紧要的,但是如果看起来很复杂,我会这样做)。

然后,还原就像git reset --hard BACKUP一样容易。

如果您已将分支推送到远程存储库 (通常是它的来源),然后成功完成了一次完整的 rebase(没有合并)( 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

使用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

对于多个提交,请记住任何提交都引用导致该提交的所有历史记录。因此,在 Charles 的回答中,将 “旧提交” 读为 “最新的旧提交”。如果您重置为该提交,那么导致该提交的所有历史记录将重新出现。这应该做您想要的。

遵循 @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)
$

如果您成功地针对远程分支重新建立了基础,并且无法git rebase --abort您仍然可以做一些技巧来保存您的工作,而不必强制执行。假设您当前错误地重新建立了your-branch称为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