如何轻松撤消git重基?冗长的手动方法是:
签出两个分支的提交父级创建并签出临时分支手工挑选所有提交重置故障的重基分支以指向临时分支
在我目前的情况下,这是可行的,因为我可以很容易地发现两个分支的提交(一个是我的东西,另一个是同事的东西)。然而,我的方法给我的印象是次优且容易出错(假设我刚刚用自己的两个分支重新建立了基础)。
澄清:我所说的是一个重基,在重基过程中,多次提交被重复,而不仅仅是一次。
如何轻松撤消git重基?冗长的手动方法是:
签出两个分支的提交父级创建并签出临时分支手工挑选所有提交重置故障的重基分支以指向临时分支
在我目前的情况下,这是可行的,因为我可以很容易地发现两个分支的提交(一个是我的东西,另一个是同事的东西)。然而,我的方法给我的印象是次优且容易出错(假设我刚刚用自己的两个分支重新建立了基础)。
澄清:我所说的是一个重基,在重基过程中,多次提交被重复,而不仅仅是一次。
当前回答
尽管这些答案应该是自动的(至少大部分是自动的),但没有一个答案是完全自动的,这让我非常恼火。我创建了一组别名来尝试解决这个问题:
# 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对我不起作用。
对我有用的东西与这里描述的相似。在.git/logs/refs中打开以重新基于分支命名的文件,找到包含“rebase finsihed”的行,类似于:
5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000 rebase finished: refs/heads/integrate onto 9e460878
签出行中列出的第二个提交。
git checkout 88552c8f
一旦确认这包含了我丢失的变化,我就分支起来,松了一口气。
git log
git checkout -b lost_changes
最简单的方法是找到分支的头部提交,因为它在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
另一种不需要进行硬重置的方法是创建一个具有您所需起点的新分支。
与其他解决方案一样,您可以使用reflog来找到正确的起点。
git reflog
(您也可以在此处使用git-log-g了解更多详细信息)
然后注意对提交SHA的引用(例如:e86a52b851e)。
最后,使用gitbranch命令。
git branch recover-branch e86a52b851e
参考:https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery#_data_recovery
如果你不想硬复位。。。
您可以从reflog签出提交,然后将其保存为新分支:
git reflog
在开始重定基础之前找到提交。您可能需要进一步向下滚动才能找到它(按Enter键或PageDown键)。记下HEAD编号并更换57:
git checkout HEAD@{57}
检查分支/提交,如果正确,则使用此HEAD创建一个新分支:
git checkout -b new_branch_name
如果您已经将分支推送到远程存储库(通常是它的源位置),然后您成功地进行了重基(没有合并)(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