如果作者已经正确地使用了强制推送,那么如何拉取新提交(并放弃旧提交)?
我知道这是糟糕的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 将在 reflog 中保留一份副本,以防您犯了错误。
如果您使用 git reset
或 git rebase
命令时出错,并意外丢失了一些本地更改,可以在 reflog 中找到这些更改。
在评论中,有用户建议使用 git reflog expire
命令并带上 --expire=now
参数,但不要运行此命令,因为这将摧毁您的安全网。拥有 reflog 的整个目的是当您运行错误命令时,Git 有时会挽救您。
基本上,这个命令会立即销毁上述示例中的 B、C、X、Y 和 Z 提交,因此您无法重新获取它们。运行此命令没有真正的好处,除了可能节省一点磁盘空间,但 Git 将在 90 天后自动清除数据,因此这个好处是短暂的。
git reset --hard
之后,您可能会意识到自己犯了某种可怕的错误,需要恢复旧数据。这就是引用日志的作用,它是一个安全网,当您进行错误的git reset
时,可以使用它来恢复数据,因此这是永久性破坏引用日志中的数据的最糟糕的时机。 - Dietrich Eppgit reset --hard
。再次强调,**除非您非常确定想要这样做(又为什么要这样做?),否则请勿销毁reflog。 - Dietrich Eppgit pull
,并让用户有一个选项来进行强制拉取。 - Sebastian Zartnergit 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
此时,您的本地更改与之前相同。您的检出已经更新到主分支或您正在工作的任何分支上的所有更改。
origin/branch
上进行交互式变基。 - Marc L.我遇到了这种情况的稍微修改过的版本。这是我所做的:
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
这两种技术都非常冗长而繁琐,但都能完成工作。