git 强制git push后如何拉?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14787776/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 08:09:28  来源:igfitidea点击:

How to pull after a forced git push?

git

提问by Andrew Legacci

Suppose I pull changes from a git repo. Then the author of the repo force pushes to the central repo. Now I can't pull since the history is rewritten.

假设我从 git repo 中提取更改。然后回购力的作者推到中央回购。现在我不能拉,因为历史被改写了。

How can I pull the new commits (and abandon the old ones), assuming that the author force-pushed the correct version?

假设作者强制推送了正确的版本,我该如何拉新提交(并放弃旧提交)?

I know this is bad git workflow, but sometimes you can't avoid this.

我知道这是糟糕的 git 工作流程,但有时您无法避免这种情况。

回答by Dietrich Epp

Throwing away your local changes

丢弃您的本地更改

If you want to discard your work, fetchand reset. For example, if you have a remote named originand a branch named master:

如果你想放弃你的工作,fetchreset. 例如,如果您有一个名为的远程origin和一个名为的分支master

$ git fetch origin
$ git reset --hard origin/master # Destroys your work

Keeping your local changes

保持本地更改

If you don't want to throw away your work, you will have to do a git rebase --onto. Suppose the old originlooks like this:

如果你不想扔掉你的工作,你将不得不做一个git rebase --onto. 假设旧的origin看起来像这样:

A ---> B ---> C
              ^
              origin/master

And you have this:

你有这个:

A ---> B ---> C ---> X ---> Y ---> Z
              ^                    ^
              |                    master
              origin/master

Now, the upstream changes change things:

现在,上游的变化改变了事情:

A ---> B ---> C ---> X ---> Y ---> Z
 \                                 ^
  ---> B'---> C'                   master
              ^          
              origin/master

You would have to run git rebase --onto origin/master <C> master, where <C>is the SHA-1 of the old origin/masterbranch before upstream changes. This gives you this:

您必须运行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

Notice how B, C, X, Y, and Z are now "unreachable". They will eventually be removed from your repository by Git. In the meantime (90 days), Git will keep a copy in the reflog in case it turns out you made a mistake.

请注意 B、C、X、Y 和 Z 现在如何“无法访问”。它们最终会被 Git 从您的存储库中删除。与此同时(90 天),Git 会在 reflog 中保留一份副本,以防你犯了错误。

Fixing mistakes

修正错误

If you git resetor git rebasewrong and accidentally lose some local changes, you can find the changes in the reflog.

如果你git resetgit rebase错了,不小心丢失了一些本地更改,你可以在 reflog 中找到这些更改。

In the comments, a user is suggesting git reflog expirewith --expire=nowbut DO NOT RUN THIS COMMANDbecause this will DESTROYyour safety net. The whole purpose of having a reflog is so that Git will sometimes save your neck when you run the wrong command.

在评论中,用户建议git reflog expire使用--expire=now不要运行此命令,因为这会破坏您的安全网。拥有 reflog 的全部目的是当你运行错误的命令时,Git 有时会保护你的脖子。

Basically, what this command will do is immediately destroy the B, C, X, Y, and Z commits in the examples above so you can't get them back. There's no real benefit to running this command, except it might save a little bit of disk space, but Git will already purge the data after 90 days so this benefit is short-lived.

基本上,此命令将立即销毁上面示例中的 B、C、X、Y 和 Z 提交,因此您无法取回它们。运行此命令并没有真正的好处,只是它可能会节省一点磁盘空间,但是 Git 会在 90 天后清除数据,因此这种好处是短暂的。

回答by keyur

I came across a slightly modified version of this scenario. Here's what I did:

我遇到了这个场景的一个稍微修改过的版本。这是我所做的:

Initial condition

初始条件

A--->B--->C--->D--->E
                    |
             local-1/master

A--->B--->C--->D--->E
                    |
              origin/master

A--->B--->C--->D--->E
                    |
             local-2/master

Squash and force push

挤压和强力推动

A--->B--->CDE
           |
    local-1/master

A--->B--->CDE
           |
     origin/master

A--->B--->C--->D--->E
                    |
             local-2/master

Sync changes on local-2/master

在 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