如何轻松撤消git重基?冗长的手动方法是:
签出两个分支的提交父级创建并签出临时分支手工挑选所有提交重置故障的重基分支以指向临时分支
在我目前的情况下,这是可行的,因为我可以很容易地发现两个分支的提交(一个是我的东西,另一个是同事的东西)。然而,我的方法给我的印象是次优且容易出错(假设我刚刚用自己的两个分支重新建立了基础)。
澄清:我所说的是一个重基,在重基过程中,多次提交被重复,而不仅仅是一次。
如何轻松撤消git重基?冗长的手动方法是:
签出两个分支的提交父级创建并签出临时分支手工挑选所有提交重置故障的重基分支以指向临时分支
在我目前的情况下,这是可行的,因为我可以很容易地发现两个分支的提交(一个是我的东西,另一个是同事的东西)。然而,我的方法给我的印象是次优且容易出错(假设我刚刚用自己的两个分支重新建立了基础)。
澄清:我所说的是一个重基,在重基过程中,多次提交被重复,而不仅仅是一次。
当前回答
最简单的方法是找到分支的头部提交,因为它在reflog中的rebase开始之前。。。
git reflog
并将当前分支重置为它(通常需要注意的是,在使用--hard选项重设种子之前要绝对确定)。
假设ref日志中的旧提交是HEAD@{2}:
git reset --hard HEAD@{2}
在Windows中,您可能需要引用引用:
git reset --hard "HEAD@{2}"
您可以通过执行git-log head@{2}(Windows:git-log“head@{2}”)来检查候选旧标头的历史记录。
如果您没有禁用每个分支的reflog,您应该能够简单地执行gitreflog branchname@{1},因为在重新连接到最终头之前,rebase会分离分支头。我会再次检查这个,尽管我最近没有验证过。
默认情况下,为非裸存储库激活所有reflog:
[core]
logAllRefUpdates = true
其他回答
假设我将master重新设置为我的功能分支,我得到了30个新的提交,这些提交会破坏一些东西。我发现通常只删除错误的提交是最简单的。
git rebase -i HEAD~31
最后31次提交的交互式重新基准(如果您选择太多,这不会有什么影响)。
只需将要删除的提交标记为“d”而不是“pick”即可。现在,提交被删除,从而有效地取消了重新基化(如果只删除重新基化时刚获得的提交)。
尽管这些答案应该是自动的(至少大部分是自动的),但没有一个答案是完全自动的,这让我非常恼火。我创建了一组别名来尝试解决这个问题:
# 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 "
警告:未测试(正则表达式可能需要调整)
我之所以没有这样做,是因为我不是百分之百地认为重新启动总是从结账开始。有人能证实这一点吗?
[如果您对函数开头的null(:)命令感到好奇,这是为别名设置bash补全的一种方法]
最简单的方法是找到分支的头部提交,因为它在reflog中的rebase开始之前。。。
git reflog
并将当前分支重置为它(通常需要注意的是,在使用--hard选项重设种子之前要绝对确定)。
假设ref日志中的旧提交是HEAD@{2}:
git reset --hard HEAD@{2}
在Windows中,您可能需要引用引用:
git reset --hard "HEAD@{2}"
您可以通过执行git-log head@{2}(Windows:git-log“head@{2}”)来检查候选旧标头的历史记录。
如果您没有禁用每个分支的reflog,您应该能够简单地执行gitreflog branchname@{1},因为在重新连接到最终头之前,rebase会分离分支头。我会再次检查这个,尽管我最近没有验证过。
默认情况下,为非裸存储库激活所有reflog:
[core]
logAllRefUpdates = true
如果您成功地重新基于远程分支,并且不能git rebase--abort,那么您仍然可以使用一些技巧来保存您的工作,并且不需要强制推送。假设您的当前分支因错误而被重新设置为分支,并正在跟踪源/分支
gitbranch-m your branch rebased#重命名当前分支git checkout origin/your branch#签出到源已知的最新状态git结帐-b您的分行检查git-log您的分支,将其与git-log分支进行比较,并定义分支中缺少的提交gitcherry-pickCOMMIT_HASH用于分支中的每个提交推动您的更改。请注意,两个本地分支与远程/您的分支关联,您应该只推送您的分支
将分支重置为其旧提示的悬空提交对象当然是最好的解决方案,因为它可以恢复以前的状态,而无需花费任何精力。但是,如果您碰巧丢失了这些提交(例如,因为您同时垃圾收集了存储库,或者这是一个新的克隆),您可以再次重新设置分支的基础。这一点的关键是--on开关。
假设你有一个想象中的主题分支,称为topic,当master的提示是0deadbeef提交时,你分支了master。在主题分支的某个时刻,您完成了git rebase master。现在您要撤消此操作。以下是操作方法:
git rebase --onto 0deadbeef master topic
这将接收所有关于主题的提交,但这些提交不在主控上,并在0个标题的顶部回放它们。
有了--on,你可以将你的历史重新整理成任何形状。
玩得开心。:-)