我意外地使用DEV分支重新设置了我的分支,然后将其推送到远程存储库。通过rebase,我选择了当前的更改,因此我的本地更改被覆盖。
我失去了我之前在rebase中的提交但是通过运行git log
找到了它。然后我跑了git checkout commitId
甚至git reset --hard commitId
。但是,在这两种情况下,我的代码库仍然在我的分支上显示最新的重新定义的代码。
如何将分支恢复到以前的状态?
检出提交的散列或对象名称会输入git文档引用的detached HEAD state。
有时候能够检出不在任何命名分支尖端的提交,甚至创建一个未被命名分支引用的新提交。让我们来看看checkout commit b时会发生什么(这里我们展示了[三种]这样做的方法):
$ git checkout v2.0 # or $ git checkout master^^ # or $ git checkout b HEAD (refers to commit 'b') | v a---b---c---d branch 'master' (refers to commit 'd') ^ | tag 'v2.0' (refers to commit 'b')
请注意,无论我们使用哪个checkout命令,
HEAD
现在都直接引用commit b。这被称为处于分离的HEAD状态。它简单地表示HEAD
引用特定的提交,而不是引用命名的分支。
正如您所观察到的,git将很乐意使用分离的HEAD创建新提交,rebase,merge等,但由于没有标记或分支引用生成的未命名分支,因此丢失它将很容易。您可以使用git log
找到您的原始提交。当你做了更激烈的手术时,git reflog
的输出是另一个值得关注的地方。
按照问题中的描述修复分支将涉及以下顺序。
HEAD
重新连接到您的分支(以下称为topic/my-branch
)topic/my-branch
重置为之前的位置origin/topic/my-branch
。
要么用力推动,要么全部完成
删除旧的远程分支并推送固定的历史记录重新连接HEAD
而不是通过其SHA-1哈希,检查您的分支名称
git checkout topic/my-branch
修复您的本地分支
接下来,用git reset --hard
把它放回原处。您将使用相同的命令,但上下文不同:HEAD
指向git checkout
而不是直接commitId之后的topic/my-branch
。
git reset --hard commitId
修复远程分支
您说您推送了您的重新分支,因此更新远程存储库以反映您的更改。在一个命令中完成所有操作的方法是
git push --force origin topic/my-branch
远程存储库的管理员可能采取了非常合理的步骤来拒绝强制推送(为什么,见下文)。如果是这样,请尝试一系列
在过去的糟糕时期,我们不得不删除非显而易见的远程分支
git push origin :topic/my-branch
但现在,它拼写了
git push --delete origin topic/my-branch
清理完毕后,现在推动您的分支机构将事情恢复到以前的状态。
git push origin topic/my-branch
如果远程禁用了强制推送和删除操作,请向具有该存储库管理访问权限的人员寻求帮助。
大多数时候,你必须努力工作才能说服git破坏工作。然而,git reset --hard
,删除远程分支和git push --force
都是锋利的工具 - 当你需要它们时很有用但是在不小心使用时很危险。和rm -rf
一样,暂停考虑你是否真正意味着你将要运行的命令。
我怀疑这里的命令顺序有些混乱。如果你这样做了
git checkout <commitId>
它将分离你的HEAD
然后你的后续
git reset --hard <commitId>
没有效果,因为目前没有分支检出。
在重置之前检查你的分支,它会没问题:
git checkout <yourBranchName>
git reset --hard <commitId>