Git:如何忽略快进并将原点 [branch] 恢复到较早的提交?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3166713/
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 04:23:22  来源:igfitidea点击:

Git: How to ignore fast forward and revert origin [branch] to earlier commit?

gitcommitreverting

提问by igniteflow

I used

我用了

git reset --hard dc082bc... 
由于一些错误的提交,将分支恢复到所需的先前状态。这让我当地的分行恢复正常。但是,我想将 'origin' 上的分支倒回到同一个提交,以便我可以重新开始。谁能告诉我如何将原始分支(不是主分支)恢复到这个提交?

I've tried git push origin master, but it gives the following error

我试过 git push origin master,但它给出了以下错误

 ! [rejected]        branch -> branch (non-fast-forward)
error: failed to push some refs to '[email protected]:xxx/xxx.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'Note about
fast-forwards' section of 'git push --help' for details.

回答by VonC

To add to my previous answer, and to address the fact that a forced git pushcan really mess up other contributors' local repos, git 1.8.5 (upcoming Q4 2013) will see a new option:

为了补充我之前的答案,并解决一个强制git push确实会弄乱其他贡献者的本地存储库的事实,git 1.8.5(2013 年第四季度即将推出)将看到一个新选项:

git push --force-with-lease

See the origin of that option in this thread:

此线程中查看该选项的来源:

if something happens at 'origin' to the branch you are forcing or deleting since you fetched to inspect it, you may end up losing other people's work.

Somebody who is unaware of the decision to rewind and rebuild the branch may attempt to push to the branch between the time you fetched to rebase it and the time you pushed to replace it with the result of the rebasing.

We can make these pushes saferby optionally allowing the user to tell "git push" this:

I am forcing/deleting, based on the assumption that the value of 'branch' is still at this object.
If that assumption no longer holds, i.e. if something happened to the branch since I started preparing for this push, please do not proceed and fail this push.

如果在origin您提取检查后强制或删除的分支发生了某些事情,您可能最终会丢失其他人的工作

不知道回滚和重建分支的决定的人可能会尝试在您提取以重新设置分支的时间和您推送以使用重新设置的结果替换它的时间之间推送到分支。

我们可以make these pushes safer选择允许用户告诉“ git push”:

我正在强制/删除,基于“分支”的值仍然在这个对象的假设。
如果这个假设不再成立,即如果自从我开始准备这次推送以来分支发生了一些事情,请不要继续并失败这次推送。

You can see the full documentation of --force-with-leasein commit 28f5d17

您可以--force-with-lease提交 28f5d17 中查看完整文档

--force-with-leasewill protect allremote refs that are going to be updated by requiring their current value to be the same as some reasonable default, unless otherwise specified;

For now, "some reasonable default" is tentatively defined as "the value of the remote-tracking branch we have for the ref of the remote being updated", and it is an error if we do not have such a remote-tracking branch.

--force-with-lease除非另有说明,否则将通过要求它们的当前值与某些合理的默认值相同来保护所有将要更新的远程引用;

目前,“一些合理的默认值”被暂时定义为“我们拥有的远程跟踪分支的值,用于更新远程的引用”,如果我们没有这样的远程跟踪分支,这是一个错误。

That explain the "lease" part of that option:

这解释了该选项的“租赁”部分:

"force-with-lease": You assume you took the lease on the ref when you fetched to decide what the rebased history should be, and you can push back only if the lease has not been broken.

" force-with-lease": 你假设你在获取时已经租用了 ref 来决定重新定位的历史应该是什么,并且只有在租约没有被破坏的情况下你才能推迟。



This is already being tested, and mentioned in the "What's cooking in git.git (Aug 2013, #07; Wed, 28)":

这已经在测试中,并在“ git.git 中的烹饪内容(2013 年 8 月,#07;周三,28 日)”中提到:

By the way, the push that overrides the usual "must fast-forward" was done using the "force-with-lease" option that has been cooking in next, like so:

顺便说一下,覆盖通常的“必须快进”的推送是使用“ force-with-lease”选项完成的next,就像这样:

$ git fetch ko next
$ anchor=$(git rev-parse --verify FETCH_HEAD)
$ for remote in ko repo gph github2
  do
    git push --force-with-lease=refs/heads/next:$anchor $remote next
  done


Note: "git push --force-with-lease" has been taught to report if the push needed to force (or fast-forwarded).

注意:“ git push --force-with-lease”已被教导报告是否需要强制(或快进)推动。

So this command is more detailed in its output with git 2.8 (March 2016)

所以这个命令在 git 2.8(2016 年 3 月)的输出中更详细

push: fix ref status reporting for --force-with-lease

The --force--with-leasepush option leads to less detailed status information than --force.
In particular, the output indicates that a reference was fast-forwarded, even when it was force-updated.

推送:修复参考状态报告 --force-with-lease

--force--with-lease推送选项导致小于详细的状态信息--force
特别是,输出表明引用是快进的,即使它被强制更新。



Beware of that option being ignored/bypassed, as explained in Git 2.13 (Q2 2017).

请注意该选项被忽略/绕过,如Git 2.13 (Q2 2017) 中所述

回答by VonC

You can try git push --forceto force the push.

您可以尝试git push --force强制推送。

--force

Usually, the command refuses to update a remote ref that is not an ancestor of the local ref used to overwrite it. This flag disables the check.
This can cause the remote repository to lose commits; use it with care.

通常,该命令拒绝更新不是用于覆盖它的本地 ref 的祖先的远程 ref。此标志禁用检查。
这可能会导致远程存储库丢失提交;小心使用它。

So if lots of people have already pulled the same branch from origin, that can cause some rebase issueon their side.
That operation can be blocked at the server side, like ebneterpoints out (in the comments):

所以如果很多人已经从原点拉取了同一个分支,那可能会导致他们这边出现一些rebase 问题
该操作可以在服务器端被阻止,就像ebneter指出的那样(在评论中):

Depending on how the remote is configured, though, this may not work
-- all of my central repos are configured with receive.denyNonFastForwards = trueand receive.denyDeletes = true, in which case any such surgery has to be done on the remote server.

但是,根据远程的配置方式,这可能不起作用
——我所有的中央存储库都配置了receive.denyNonFastForwards = truereceive.denyDeletes = true,在这种情况下,任何此类手术都必须在远程服务器上完成。

However, in the case of GitHub, such settings are not readily availablefor the user managing its GitHub repo.
So if you git push --forceby mistake, all you are left is opening a case to the GitHub support, for them to check their local (i.e. "GitHub") reflogs and see if they can restore old commits.
(Since reflogs are local, like I have been remembered recently. So commits which are replaced by new ones during a push --forceare only still visible, if no 'git gc' or 'git prune' already took place, at the GitHubserver side)

但是,在 GitHub 的情况下,管理其 GitHub 存储库的用户不容易获得此类设置
因此,如果您git push --force弄错了,剩下的就是向 GitHub 支持部门开一个案例,让他们检查他们的本地(即“GitHub”)引用日志,看看他们是否可以恢复旧的提交。
(因为 reflogs 是本地的,就像我最近被记住的那样。所以在GitHub服务器端push --force,如果没有 ' git gc' 或 ' git prune' 已经发生,则在 a 期间被新提交替换的提交仍然可见)

So Marco Ceppiinsists (in the comments):

所以Marco Ceppi坚持(在评论中):

this could really mess up other contributors local repos if you force pushes - though are times that it is just a necessary evil (I've maybe had to do this two times in my lifespan of using Git)

如果您强制推送,这可能真的会弄乱其他贡献者的本地存储库 - 尽管有时它只是一种必要的邪恶(在我使用 Git 的生命周期中,我可能不得不这样做两次)

回答by xgqfrms

git reset&& git pushwith force overwrite

git reset&&git push强制覆盖

# master commit uid
$ git reset --hard b9e3f7f2f66674901b467183dd81d493e50677f5

# git push branch_name --force

# local master
$ git push origin master --force

# remote master
$ git push origin/master -f

refs

参考

In Git, what is the difference between origin/master vs origin master?

在 Git 中,origin/master 与 origin master 之间有什么区别?

https://git-scm.com/docs/git-reset

https://git-scm.com/docs/git-reset