撤消git rebase

问题描述 投票:2785回答:18

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

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

  • git checkout两个分支的提交父级
  • 然后从那里创建一个临时分支
  • 樱桃 - 手工挑选所有提交
  • 用手动创建的分支替换我重新定位的分支

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

然而,我的方法让我感到不理想和容易出错(假设我刚刚用自己的2个分支重新定位)。

有任何想法吗?

澄清:我正在谈论一个rebase,在此期间重播了一堆提交。不仅仅是一个。

git rebase git-rebase undo
18个回答
3911
投票

最简单的方法是找到分支的头部提交,就像它在reflog中的rebase开始之前一样......

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}")来检查候选老头的历史。

如果你没有禁用每个分支reflogs你应该能够简单地做git reflog branchname@{1}作为rebase分离分支头,然后重新连接到最终头。我会仔细检查这个,尽管我最近没有证实这一点。

默认情况下,为非裸存储库激活所有reflog:

[core]
    logAllRefUpdates = true

15
投票

对于多次提交,请记住任何提交都会引用导致该提交的所有历史记录。所以在查尔斯的回答中,将“旧提交”称为“最新的提交”。如果重置为该提交,则会重新出现导致该提交的所有历史记录。这应该做你想要的。


11
投票

根据@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)
$

11
投票

如果你成功地反对远程分支而不能git rebase --abort你仍然可以做一些技巧来保存你的工作,而不是强迫推动。假设您错误重新定位的当前分支称为your-branch并且正在跟踪origin/your-branch

  • git branch -m your-branch-rebased#rename current branch
  • git checkout origin/your-branch#checkout到已知的最新状态
  • git checkout -b your-branch
  • 检查git log your-branch-rebased,与git log your-branch比较并定义your-branch缺少的提交
  • git cherry-pick COMMIT_HASHyour-branch-rebased的每次提交
  • 推动你的改变。请注意,两个当地分支机构与remote/your-branch相关联,您应该只推动your-branch

4
投票

假设我将master重新绑定到我的功能分支,并且我得到了30个新的提交,这些提交会破坏某些功能。我发现通常最简单的方法就是删除糟糕的提交。

git rebase -i HEAD~31

最近31次提交的交互式rebase(如果选择的方式太多,则不会受到影响)。

简单地接受你想要删除的提交,并用“d”而不是“pick”标记它们。现在删除了提交,有效地删除了rebase(如果只删除了刚刚进行rebased时提交的提交)。


2
投票

对于新手/任何害怕进行硬重置的人,您可以从reflog中签出提交,然后将其保存为新分支。

git reflog

在开始重新定位之前找到提交。您可能需要向下滚动才能找到它(按Enter或PageDown)。记下HEAD编号并替换57:

git checkout HEAD@{57}

查看分支/提交,如果看起来不错,请使用此HEAD创建新分支:

git checkout -b new_branch_name

1
投票

如果您在分支机构,您可以使用:

git reset --hard @{1}

不仅HEAD的参考日志(由git reflog获得),每个分支也有reflogs(由git reflog <branch>获得)。所以,如果你在master,那么git reflog master将列出该分支的所有更改。你可以参考master@{1}master@{2}等的变化。

git rebase通常会多次更改HEAD,但当前分支只会更新一次。

@{1}只是一个shortcut for the current branch,所以如果你在master@{1}它等于master

如果你在互动的git reset --hard ORIG_HEAD中使用git resetrebase将无效。


1
投票

我通常做的是git reset #commit_hash

到最后一次提交,我认为rebase没有效果。

然后git pull

现在你的分支应该与master完全匹配,并且不应该在其中使用rebased提交。

现在,我们可以在这个分支上挑选提交。


-1
投票

git reset --hard origin / {branchName}

是重置由rebase完成的所有本地更改的正确解决方案。


-3
投票

如果你在git rebase中混淆了一些东西,例如git rebase --abort,虽然你有未提交的文件,他们将丢失,git reflog将无济于事。这发生在我身上,你需要在这里开箱即用。如果你像我一样幸运并使用IntelliJ Webstorm那么你可以right-click->local history并且可以恢复到你的文件/文件夹的先前状态,无论你使用版本控制软件做了什么错误。另一个故障安全运行总是好的。


1382
投票

实际上,rebase将你的起点保存到ORIG_HEAD所以这通常很简单:

git reset --hard ORIG_HEAD

然而,resetrebasemerge都将你原来的HEAD指针保存到ORIG_HEAD所以,如果你已经完成了任何这些命令,因为你试图撤消rebase然后你将不得不使用reflog。


355
投票

查尔斯的答案有效,但你可能想这样做:

git rebase --abort

reset之后清理。

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


102
投票

git reflog将显示rebase之前和之后的所有更改,并允许您找到要重置的正确的更改。但我很惊讶没有人提到这个其他超级简单的方法:

Rebase将旧状态保留为ORIG_HEAD,因此您可以通过运行以下命令恢复最后一个rebase:

git reset --hard ORIG_HEAD

84
投票

将分支重置为其旧提示的悬空提交对象当然是最佳解决方案,因为它可以在不花费任何精力的情况下恢复之前的状态。但是,如果您碰巧丢失了这些提交(因为您在此期间垃圾收集了您的存储库,或者这是一个新的克隆),您可以再次重新绑定该分支。关键是--onto开关。

假设你有一个主题分支富有想象力地称为topic,当master的尖端是master提交时你分支0deadbeef。在topic分支的某个时刻,你做了git rebase master。现在你要撤消这个。这是如何做:

git rebase --onto 0deadbeef master topic

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

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

玩得开心。 :-)


68
投票

在我做任何非常重要的操作之前,我实际上在分支上放了一个备份标签(大多数rebase都很简单,但如果它看起来很复杂的话,我就会这样做)。

然后,恢复就像git reset --hard BACKUP一样简单。


60
投票

如果您已将分支推送到远程存储库(通常是它的原点)然后您已经完成了成功的rebase(没有合并)(git rebase --abort给出“没有正在进行的rebase”),您可以使用命令轻松地重置分支:

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

52
投票

如果您尚未完成rebase并且在其中间,则以下工作:

git rebase --abort

19
投票

使用reflog并不适合我。

对我有用的是与here描述的类似。打开以重新分支的分支命名的.git / logs / refs中的文件,找到包含“rebase finsihed”的行,如:

5fce6b51 88552c8f Kris Leech <[email protected]> 1329744625 +0000  rebase finished: refs/heads/integrate onto 9e460878

签出该行上列出的第二个提交。

git checkout 88552c8f

一旦确认,这包含了我失去的变化,我分支并松了一口气。

git log
git checkout -b lost_changes
© www.soinside.com 2019 - 2024. All rights reserved.