如何轻松撤消git重基?冗长的手动方法是:
签出两个分支的提交父级创建并签出临时分支手工挑选所有提交重置故障的重基分支以指向临时分支
在我目前的情况下,这是可行的,因为我可以很容易地发现两个分支的提交(一个是我的东西,另一个是同事的东西)。然而,我的方法给我的印象是次优且容易出错(假设我刚刚用自己的两个分支重新建立了基础)。
澄清:我所说的是一个重基,在重基过程中,多次提交被重复,而不仅仅是一次。
如何轻松撤消git重基?冗长的手动方法是:
签出两个分支的提交父级创建并签出临时分支手工挑选所有提交重置故障的重基分支以指向临时分支
在我目前的情况下,这是可行的,因为我可以很容易地发现两个分支的提交(一个是我的东西,另一个是同事的东西)。然而,我的方法给我的印象是次优且容易出错(假设我刚刚用自己的两个分支重新建立了基础)。
澄清:我所说的是一个重基,在重基过程中,多次提交被重复,而不仅仅是一次。
当前回答
如果您已经将分支推送到远程存储库(通常是它的源位置),然后您成功地进行了重基(没有合并)(gitrebase--abort给出“没有正在进行的重基”),您可以使用命令:
git reset--硬原点/{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
其他回答
假设我将master重新设置为我的功能分支,我得到了30个新的提交,这些提交会破坏一些东西。我发现通常只删除错误的提交是最简单的。
git rebase -i HEAD~31
最后31次提交的交互式重新基准(如果您选择太多,这不会有什么影响)。
只需将要删除的提交标记为“d”而不是“pick”即可。现在,提交被删除,从而有效地取消了重新基化(如果只删除重新基化时刚获得的提交)。
实际上,rebase将您的起点保存到ORIG_HEAD,因此这通常很简单:
git reset --hard ORIG_HEAD
然而,reset、rebase和merge都会将原始HEAD指针保存到ORIG_HEAD中,因此,如果您在尝试撤消rebase之后执行了这些命令,则必须使用reflog。
我通常做的是git reset#commit_hash
到最后一次提交,我认为rebase没有效果。
然后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
尽管这些答案应该是自动的(至少大部分是自动的),但没有一个答案是完全自动的,这让我非常恼火。我创建了一组别名来尝试解决这个问题:
# 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补全的一种方法]