撤消git重基

撤消git重基,git,rebase,git-rebase,undo,Git,Rebase,Git Rebase,Undo,有人知道如何轻松地撤销git的重基吗 我想到的唯一方法是手动操作: git签出将父级提交到两个分支 然后从那里创建一个临时分支 cherry手工挑选所有提交的文件 用手动创建的分支替换我在其中重新设置基础的分支 在我目前的情况下,这是可行的,因为我可以很容易地发现来自两个分支的提交—一个是我的东西,另一个是我同事的东西 然而,我的方法给我的印象是次优且容易出错——比如说,我刚刚用自己的两个分支重新设置了基准 有什么想法吗 澄清:我说的是一个重基,在此期间重播了一系列提交。不仅仅是一个。最简单的方

有人知道如何轻松地撤销git的重基吗

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

git签出将父级提交到两个分支 然后从那里创建一个临时分支 cherry手工挑选所有提交的文件 用手动创建的分支替换我在其中重新设置基础的分支 在我目前的情况下,这是可行的,因为我可以很容易地发现来自两个分支的提交—一个是我的东西,另一个是我同事的东西

然而,我的方法给我的印象是次优且容易出错——比如说,我刚刚用自己的两个分支重新设置了基准

有什么想法吗


澄清:我说的是一个重基,在此期间重播了一系列提交。不仅仅是一个。

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

并且在使用-hard选项重置之前,使用关于绝对确定的常规警告将当前分支重置为它

假设旧提交是ref日志中的HEAD@{5}:

git reset --hard HEAD@{5}
在Windows中,您可能需要引用以下参考:

只需执行git log head@{5}Windows:git log head@{5},就可以检查候选旧head的历史记录

如果您没有禁用每个分支的reflogs,那么您应该能够简单地执行git reflog branchname@{1},因为在重新连接到最终的分支头之前,rebase会分离分支头。我会再次检查这个,虽然我最近没有验证过

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

[core]
    logAllRefUpdates = true

对于多个提交,请记住,任何提交都会引用该提交之前的所有历史记录。因此,在查尔斯的回答中,将旧承诺解读为旧承诺中最新的一个。如果重置为该提交,则提交之前的所有历史记录都将重新出现。这应该可以满足您的需要。

将分支重置为其旧提示的悬空提交对象当然是最好的解决方案,因为它可以在不花费任何精力的情况下恢复以前的状态。但是如果你碰巧丢失了这些f.ex。因为您同时对存储库进行了垃圾收集,或者这是一个新的克隆,所以您始终可以重新设置分支的基础。关键是-接通开关

假设你有一个主题分支,富有想象力地称之为主题,当主旨的提示是0时,你从主旨分支出来。在主题分支的某个时候,您做了git rebase master。现在要撤消此操作。以下是方法:

git rebase --onto 0deadbeef master topic
这将获取主题上不在master上的所有提交,并在0deadbeef上重播它们

使用-On,你可以将你的历史重新整理成几乎任何形状


玩得开心-

实际上,rebase会将起点保存到原点,因此这通常很简单:

git reset --hard ORIG_HEAD

但是,重置、重设和合并都会将原始头指针保存到ORIG_头中,因此,如果您在尝试撤消重设后执行了这些命令中的任何一个,那么您将不得不使用reflog。

在执行任何非平凡操作之前,我实际上在分支上放置了一个备份标记,大多数重设都是微不足道的,但如果它看起来很复杂,我会这么做

然后,恢复就像git reset-硬备份一样简单。

可以工作,但您可能需要执行以下操作:

git rebase --abort
重置后进行清理

否则,您可能会收到消息“Interactive rebase已启动”。

使用reflog对我不起作用

对我起作用的与所描述的相似。在.git/logs/refs中打开以重新设置基址的分支命名的文件,并找到包含已设置基址的行,类似于:

5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000  rebase finished: refs/heads/integrate onto 9e460878
一旦确认这包含了我丢失的变化,我就分支并松了一口气

git log
git checkout -b lost_changes

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

注意-i必须在没有-i的情况下简单地执行git-rebase-abort,而不是执行git-rebase-i-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不会提供任何正在进行的基础,您可以使用 命令:

git重置-硬原点/{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中搞砸了一些事情,例如git rebase-abort,而您有未提交的文件,那么这些文件将丢失,git reflog也帮不上忙。这件事发生在我身上,你需要跳出框框思考。如果您像我一样幸运,并且使用IntelliJ Webstorm,那么您可以右键单击->本地历史,并可以恢复到文件/文件夹的以前状态,无论您在版本控制软件中犯了什么错误。再次运行故障保护总是很好的。

如果您成功地重新设置了基础 d针对远程分支,无法git重新设置基础-中止您仍然可以使用一些技巧来保存您的工作,而不必强制推送。 假设您的当前分支被错误地重定了基础,称为您的分支,并且正在跟踪来源/您的分支

git branch-m您的分支重新命名当前分支 git checkout origin/您的分支签出到origin已知的最新状态 git checkout-b您的分支 检查git log(git log your branch rebased),将其与git log(git log your branch)进行比较,并定义分支中缺少的提交 git cherry pick COMMIT\u哈希,用于重新设置分支中的每个提交 推动您的更改。请注意,两个本地分支与远程/您的分支关联,您应该只推送您的分支
假设我将master重设为我的特性分支,我得到了30个新的提交,这些提交破坏了某些东西。我发现通常删除错误的提交是最简单的

git rebase -i HEAD~31
在过去的31个月里,如果你选择了太多的方式,那么交互式的重新基址并没有什么坏处


只需将您想要删除的提交标记为d,而不是pick。现在,如果您仅删除重定基址时刚获得的提交,则提交将被删除,从而有效地撤消重定基址。

如果您在分支上,则可以使用:

git reset --hard @{1}
不仅有git reflog获得的HEAD参考日志,还有git reflog获得的每个分支的reflog。所以,如果您在master上,那么git reflog master将列出对该分支的所有更改。您可以通过master@{1}、master@{2}等引用这些更改

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

@{1} 只是一个,所以如果你在master上,它等于master@{1}

git reset-如果在交互式重新基址期间使用git reset,则硬ORIG_头将不起作用

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

如果不想执行硬重置

您可以从reflog签出提交,然后将其另存为新分支:

git reflog
在开始重定基址之前找到提交。您可能需要进一步向下滚动才能找到它,请按Enter或PageDown。记下机头编号并更换57:

git checkout HEAD@{57}
检查分支/提交,如果正确,则使用此标头创建新分支:

git checkout -b new_branch_name
我通常做的是 git重置提交散列

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

然后,git pull

现在,您的分支应该与主分支完全匹配,并且重定基础的提交不应该在其中


现在,您可以直接选择此分支上的提交。

我尝试了重置和重新登录的所有建议,但没有成功。恢复IntelliJ的本地历史解决了丢失文件的问题。尽管这些答案至少大部分应该是自动的,但没有一个是完全自动的,这让我非常恼火。我创建了一组别名来尝试解决此问题:

# Useful commands
#################

# Undo the last rebase
undo-rebase = "! f() { : git reset ; PREV_COMMIT=`git x-rev-before-rebase` && git reset --merge \"$PREV_COMMIT\" \"$@\";}; f"

# See what changed since the last rebase
rdiff = "!f() { : git diff ; git diff `git x-rev-before-rebase` "$@";}; f"

# Helpers
########
# Get the revision before the last rebase started
x-rev-before-rebase = !git reflog --skip=1 -1 \"`git x-start-of-rebase`\" --format=\"%gD\"

# Get the revision that started the rebase
x-start-of-rebase = reflog --grep-reflog '^rebase (start)' -1 --format="%gD"
你应该能够调整这一点,允许返回任意数量的回退非常容易杂耍的参数是最棘手的部分,这可能是有用的,如果你做了一个快速连续的回退数量和混乱的东西了

警告 如果任何提交消息以rebase start开头,它将变得混乱。请不要这样做。您可以通过为您的正则表达式匹配以下内容,使正则表达式更具弹性,以改善这种情况:

--grep-reflog "^rebase (start): checkout " 
警告:未测试的正则表达式可能需要调整

我之所以没有这样做,是因为我不是100%地认为回扣总是从结帐开始的。有人能证实这一点吗


[如果您对函数开头的null:命令感到好奇,这是一种为别名设置bash补全的方法]

Git reflog非常棒,请记住,使用Scott Chacon的git log-g技巧可以获得更好的格式输出。@Zach:git rebase-abort-i使用-abort没有任何意义-abort用于放弃尚未完成的rebase-可能是因为存在冲突,也可能是因为它是交互式的,或者两者兼而有之;问题的关键不在于撤销成功的再基础。根据您所处的情况,您可以使用rebase-abort或reset-hard。你不需要同时做这两件事。以防万一,先做一个备份:git标签备份。如果出现问题,您可以返回到它:git reset-hard backup如果您进行了大量提交,那么您要查找的头@{}将以commit:而不是rebase:开头。听起来很明显,但这让我有点困惑。在一次意外的重新设置后加入派对:D。一个git重置硬的ORIG_头不会在意外的重新设置后立即起作用吗?我也是这样做的。git diff备份也很有用。请确保您更改了您想要更改的内容。我以前也这样做过,但由于我对reflog更熟悉了,我觉得不再有必要这样做。reflog基本上是在每次你改变头部时代表你这么做的。好吧,我更喜欢有意义的名字,因为se

在reflog中搜索正确的项有时一点也不有趣。实际上,您甚至不需要创建备份分支,您可以简单地使用branchName@{n}语法,这里n是分支指针的第n个优先位置。例如,如果您将featureA分支重设到主分支上,但不喜欢重设的结果,那么您可以简单地执行git reset-hard featureA@{1}将分支重设回重设之前的位置。您可以在上阅读有关分支@{n}语法的更多信息。实际上,您甚至不需要使用上述语法,根据,分支的原始头临时存储在ORIG_头中。但是使用备份分支标签的技术也很有效,只需要更多的步骤。我认为这是最好的选择,因为它具有灵活性。我将b1从主节点分支出来,然后将b1重设为新的分支b2,然后希望将b1恢复为基于主节点。我只是喜欢吉特-谢谢!这是这里最好的选择!它保留了我对当前分支的所有更改,并删除了所有不需要的更改!我要说的是,通过把-上-和-我结合起来,你可以把你的历史重新整理成几乎任何形式。在mac上使用gitk或gitx查看您所做的形状:-。出于某种原因,您的回答让我意识到我可以进行git rebase-我提交,然后编辑我不满意的提交:还要注意,在rebase过程中,您可以排除提交,或挤压提交;如果没有指向原始节点的指针或通过reflog筛选,这些更改是不可恢复的,因此cherrypicking将不起作用。或者:哇-从该链接中,有一个警告:我丢失了分支的历史记录,但在本例中,这并不重要。我只是很高兴找回了我的改变?如果ORIG_HEAD不再有用,还可以使用branchName@{n}语法,其中n是分支指针的第n个优先位置。例如,如果您将featureA分支重设到主分支上,但不喜欢重设的结果,那么您可以简单地执行git reset-hard featureA@{1}将分支重设回重设之前的位置。您可以在上阅读有关分支@{n}语法的更多信息。这是最简单的。接着是git的重新基址-尽管如此。@DaBlick在git 2.17.0上完全成功的重新基址并且没有冲突之后,这对我来说效果很好。让我补充一下:git reset-hard ORIG_HEAD可以反复使用,一次又一次地回滚。比如说,如果A--rebase to--B--rebase to--C,现在我在C,我可以通过使用两次git reset-hard ORIG返回到A_HEAD@Seph你能解释一下为什么建议继续使用git-rebase-abort吗?这一个删除了我提示中的| rebase部分+1这不是问题所在。问题是如何撤销已完成的重基。应该是对Charles answer的评论,因为它不回答其onHm上的问题,我不必这样做。这是我需要的答案!不管有没有问题,这个答案似乎是缺少的部分之一。git rebase-abort中止活动的rebase,它不会撤消一个rebase。另外,同时使用两个VCS是个坏主意。这是Jetbrains软件中的一个不错的功能,但你不应该同时使用这两个功能。最好只是学习Git,尤其是在回答有关Git的堆栈溢出问题时。这对我来说是正确的答案。Rebase和Rebase之前的commit具有相同的提交ID,返回头{1}不会恢复Rebase!如果硬重置为原点/分支,则可能会丢失头部和该点之间的更改。一般来说,你不希望这样。这正是我想要的。所以,谢谢!以前从未使用过本地历史记录,但对于我来说,这是恢复一些意外重定基址的代码的最简单的选择。非常好,但有些隐藏的功能。这是行不通的。你已经删除了所有的工作。Rebase重写提交,因此在大多数情况下,通过这样做,您将同时取消原始提交和重写提交。如果有人知道更好的方法来获得正确的提交,我将非常感谢您的编辑:
git checkout HEAD@{57}
git checkout -b new_branch_name
# Useful commands
#################

# Undo the last rebase
undo-rebase = "! f() { : git reset ; PREV_COMMIT=`git x-rev-before-rebase` && git reset --merge \"$PREV_COMMIT\" \"$@\";}; f"

# See what changed since the last rebase
rdiff = "!f() { : git diff ; git diff `git x-rev-before-rebase` "$@";}; f"

# Helpers
########
# Get the revision before the last rebase started
x-rev-before-rebase = !git reflog --skip=1 -1 \"`git x-start-of-rebase`\" --format=\"%gD\"

# Get the revision that started the rebase
x-start-of-rebase = reflog --grep-reflog '^rebase (start)' -1 --format="%gD"
--grep-reflog "^rebase (start): checkout "