撤消 git rebase

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/134882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 05:49:10  来源:igfitidea点击:

Undoing a git rebase

gitrebasegit-rebaseundo

提问by webmat

Does anybody know how to easily undo a git rebase?

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

The only way that comes to mind is to go at it manually:

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

  • git checkout the commit parent to both of the branches
  • then create a temp branch from there
  • cherry-pick all commits by hand
  • replace the branch in which I rebased by the manually-created branch
  • git checkout 提交父级到两个分支
  • 然后从那里创建一个临时分支
  • 手工挑选所有提交
  • 用手动创建的分支替换我重新定位的分支

In my current situation this is gonna work because I can easily spot commits from both branches (one was my stuff, the other was my colleague's stuff).

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

However my approach strikes me as suboptimal and error-prone (let's say I had just rebased with 2 of my own branches).

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

Any ideas?

有任何想法吗?

Clarification: I'm talking about a rebase during which a bunch of commits were replayed. Not only one.

澄清:我说的是 rebase,在此期间重放了一堆提交。不止一个。

回答by CB Bailey

The easiest way would be to find the head commit of the branch as it was immediately before the rebase started in the reflog...

最简单的方法是找到分支的头部提交,因为它是在reflog 中rebase 开始之前的那一刻......

git reflog

and to reset the current branch to it (with the usual caveats about being absolutely sure before reseting with the --hardoption).

并将当前分支重置为它(通常的警告是在使用--hard选项重置之前绝对确定)。

Suppose the old commit was HEAD@{5}in the ref log:

假设旧提交HEAD@{5}在引用日志中:

git reset --hard HEAD@{5}

In Windows, you may need to quote the reference:

在 Windows 中,您可能需要引用参考:

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

You can check the history of the candidate old head by just doing a git log HEAD@{5}(Windows:git log "HEAD@{5}").

您只需执行git log HEAD@{5}( Windows:) 即可查看候选老头的历史记录git log "HEAD@{5}"

If you've not disabled per branch reflogs you should be able to simply do git reflog branchname@{1}as a rebase detaches the branch head before reattaching to the final head. I would double check this, though as I haven't verified this recently.

如果你没有禁用每个分支的引用日志,你应该能够简单地做,git reflog branchname@{1}因为 rebase 在重新连接到最终头之前分离分支头。我会仔细检查这个,虽然我最近没有验证过。

Per default, all reflogs are activated for non-bare repositories:

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

[core]
    logAllRefUpdates = true

回答by Pat Notz

Actually, rebase saves your starting point to ORIG_HEADso this is usually as simple as:

实际上,rebase 可以保存您的起点,ORIG_HEAD因此这通常很简单:

git reset --hard ORIG_HEAD

However, the reset, rebaseand mergeall save your original HEADpointer into ORIG_HEADso, if you've done any of those commands since the rebase you're trying to undo then you'll have to use the reflog.

但是,reset,rebasemerge所有将您的原始HEAD指针保存到ORIG_HEADso 中,如果您在尝试撤消变基后执行了这些命令中的任何一个,那么您将不得不使用引用日志。

回答by Allan

Charles's answer works, but you may want to do this:

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

git rebase --abort

to clean up after the reset.

后清理reset

Otherwise, you may get the message “Interactive rebase already started”.

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

回答by Aristotle Pagaltzis

Resetting the branch to the dangling commit object of its old tip is of course the best solution, because it restores the previous state without expending any effort. But if you happen to have lost those commits (f.ex. because you garbage-collected your repository in the meantime, or this is a fresh clone), you can always rebase the branch again. The key to this is the --ontoswitch.

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

Let's say you had a topic branch imaginatively called topic, that you branched off masterwhen the tip of masterwas the 0deadbeefcommit. At some point while on the topicbranch, you did git rebase master. Now you want to undo this. Here's how:

假设您有一个想象性地称为 的主题分支topicmaster当提示master0deadbeef提交时,您将其分支。在topic分支上的某个时候,你做了git rebase master。现在您想撤消此操作。就是这样:

git rebase --onto 0deadbeef master topic

This will take all commits on topicthat aren't on masterand replay them on top of 0deadbeef.

这将获取所有topic未打开的提交master并在0deadbeef.

With --onto, you can rearrange your history into pretty much any shape whatsoever.

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

Have fun. :-)

玩得开心。:-)

回答by Alex Gontmakher

I actually put a backup tag on the branch before I do any nontrivial operation (most rebases are trivial, but I'd do that if it looks anywhere complex).

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

Then, restoring is as easy as git reset --hard BACKUP.

然后,恢复就像git reset --hard BACKUP.

回答by Maksym

In case you had pushed your branch to remote repository(usually it's origin) and then you've done a succesfull rebase (without merge) (git rebase --abortgives "No rebase in progress") you can easily reset branchusing command:

如果您已将分支推送到远程存储库(通常是源代码),然后您已经成功完成了 rebase(没有合并)(git rebase --abort给出“No rebase in progress”),您可以使用命令轻松重置分支

git reset --hard origin/{branchName}

git reset --hard origin/{branchName}

Example:

例子:

$ ~/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

回答by Kris

Using reflogdidn't work for me.

使用reflog对我不起作用。

What worked for me was similar to as described here. Open the file in .git/logs/refs named after the branch that was rebased and find the line that contains "rebase finsihed", something like:

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

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

Checkout the second commit listed on the line.

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

git checkout 88552c8f

Once confirmed this contained my lost changes I branched and let out a sigh of relief.

一旦确认这包含了我丢失的更改,我就松了一口气。

git log
git checkout -b lost_changes

回答by Greg Hewgill

For multiple commits, remember that any commit references all the history leading up to that commit. So in Charles' answer, read "the old commit" as "the newest of the old commits". If you reset to that commit, then all the history leading up to that commit will reappear. This should do what you want.

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

回答by Matheus Felipe

Following the solution of @Allan and @Zearin, I wish I could simply do a comment though but I don't enough reputation, so I have used the following command:

按照@Allan 和@Zearin 的解决方案,我希望我可以简单地发表评论,但我没有足够的声誉,所以我使用了以下命令:

Instead of doing git rebase -i --abort(note the -i) I had to simply do git rebase --abort(withoutthe -i).

而不是做git rebase -i --abort(注意-i),我不得不简单地做git rebase --abort没有-i)。

Using both -iand --abortat the same time causes Git to show me a list of usage/options.

同时使用-i,并--abort在同一时间将导致混帐给我的使用/选项列表。

So my previous and current branch status with this solution is:

因此,我以前和当前使用此解决方案的分支状态是:

matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort

matbhz@myPc /my/project/environment (branch-123)
$

回答by Sergey P. aka azure

If you successfully rebased against remote branch and can not git rebase --abortyou still can do some tricks to save your work and don't have forced pushes. Suppose your current branch that was rebased by mistake is called your-branchand is tracking origin/your-branch

如果您成功地针对远程分支重新定位并且不能,git rebase --abort您仍然可以做一些技巧来保存您的工作并且没有强制推送。假设您当前错误地重新定位的分支被调用your-branch并且正在跟踪origin/your-branch

  • git branch -m your-branch-rebased# rename current branch
  • git checkout origin/your-branch# checkout to latest state that is known to origin
  • git checkout -b your-branch
  • check git log your-branch-rebased, compare to git log your-branchand define commits that are missing from your-branch
  • git cherry-pick COMMIT_HASHfor every commit in your-branch-rebased
  • push your changes. Please aware that two local branches are associated with remote/your-branchand you should push only 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