假设我从 git 存储库中提取更改。然后repo的作者强制推送到中央repo。现在我无法拉动,因为历史被重写了。
假设作者强制推送了正确的版本,我如何提取新的提交(并放弃旧的提交)?
我知道这是糟糕的 git 工作流程,但有时你无法避免这一点。
如果您想放弃您的工作,
fetch
和reset
。 例如,如果您有一个名为 origin
的遥控器和一个名为 master
的分支:
$ git fetch origin
$ git reset --hard origin/master # Destroys your work
如果你不想扔掉你的工作,你就必须做一个
git rebase --onto
。假设旧的 origin
看起来像这样:
A ---> B ---> C
^
origin/master
你有这个:
A ---> B ---> C ---> X ---> Y ---> Z
^ ^
| master
origin/master
现在,上游的变化改变了一切:
A ---> B ---> C ---> X ---> Y ---> Z
\ ^
---> B'---> C' master
^
origin/master
您必须运行
git rebase --onto origin/master <C> master
,其中 <C>
是上游更改之前旧 origin/master
分支的 SHA-1。 这给你这个:
A ---> B ---> C ---> X ---> Y ---> Z
\
---> B'---> C'---> X'---> Y'---> Z'
^ ^
| master
origin/master
注意 B、C、X、Y 和 Z 现在如何“无法访问”。它们最终将被 Git 从您的存储库中删除。 在此期间(90 天),Git 会在引用日志中保留一份副本,以防您犯了错误。
如果您
git reset
或git rebase
错误并且不小心丢失了一些本地更改,您可以在reflog中找到更改。
在评论中,用户建议使用
git reflog expire
--expire=now
,但不要运行此命令,因为这会破坏您的安全网。 拥有 reflog 的全部目的是,当你运行错误的命令时,Git 有时会救你一命。
基本上,此命令将立即销毁上面示例中的 B、C、X、Y 和 Z 提交,这样您就无法将它们恢复。 运行此命令没有真正的好处,只是它可能会节省一点磁盘空间,但 Git 会在 90 天后清除数据,因此这种好处是短暂的。
如果您没有有本地提交,这将从强制推送中恢复您的结账。您将了解远程分支的最新情况,并能够在此之后提交您的本地工作。
git fetch
git stash
git reset --hard origin/master # destroys your work
git stash pop # restores your work as local changes
git mergetool # fix any conflicts
此时,您的本地更改与之前一样。您的结帐是最新的,包含 master 或您正在工作的任何分支上的所有更改。
我遇到了这个场景的稍微修改过的版本。这就是我所做的:
A--->B--->C--->D--->E
|
local-1/master
A--->B--->C--->D--->E
|
origin/master
A--->B--->C--->D--->E
|
local-2/master
A--->B--->CDE
|
local-1/master
A--->B--->CDE
|
origin/master
A--->B--->C--->D--->E
|
local-2/master
$ git reset --soft B
A--->B---> (local uncommitted changes)
|
local-2/master
$ git stash save "backup"
A--->B
|
local-2/master
$ git pull origin master
A--->B--->CDE
|
local-2/master
如果您没有对本地分支进行任何更改,您可以尝试以下命令序列。请记住,这是实现您所要求的目标的一种粗略方法。
git checkout master
git pull
git remote update origin -p
git branch -D myBranch
git checkout myBranch
git remote update origin -p
是可选的。
如果您进行了更改并且您不关心本地分支的内容,您可以尝试以下操作:
git stash
git stash drop
git checkout master
git pull
git remote update origin -p
git branch -D myBranch
git checkout myBranch
这两种技术都非常漫长且繁琐。但一定要把工作做好。