Git:如何忽略快进并将[分支]回滚到早期提交?

10

由于存在一些不良提交,我使用

git reset --hard dc082bc...
恢复分支到所需的以前状态,这样可以使本地分支回退。但是,我想将'origin'上的分支也回退到相同的提交状态,以便重新开始。请问有谁知道如何将'origin'(而不是主分支)分支还原到该提交?

我尝试过git push origin master,但出现以下错误:

 ! [rejected]        branch -> branch (non-fast-forward)
error: failed to push some refs to 'git@github.com: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.

1
你很快就会(git1.8.5,2013年第四季度)更加小心地执行git push --force命令。请参见下面的我的新答案 - VonC
3个回答

33

为了补充previous answer,并解决强制执行git push可能会破坏其他贡献者本地仓库的问题,即将在2013年第四季度发布的Git 1.8.5中将会增加一个新选项:

git push --force-with-lease

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

如果在您获取以检查它为目的而强制或删除的分支的'origin'时发生了什么,您可能会丢失其他人的工作

不知道倒回和重建分支决定的人可能会尝试在您获取并重新安排它的时间与您推送以替换重建结果的时间之间向分支推送。

我们可以通过可选允许用户告诉“git push”这一点来使这些推送更加安全

我正在强制/删除,基于'branch'的值仍然在此对象上的假设。
如果该假设不再成立,即如果自我准备此推送以来分支发生了某些变化,请不要继续并失败此推送。

你可以查看commit 28f5d17--force-with-lease的完整文档。

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

目前,“某些合理的默认值”被初步定义为“我们为正在更新的远程引用的引用拥有的远程跟踪分支的值”,如果我们没有这样的远程跟踪分支,则会出现错误。

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

"force-with-lease": 当您获取信息以决定变基历史记录时,您假设已经对引用进行过租赁,并且只有在租约未被打破时才能回推。


这已经在测试中,并在 "Git.git中有什么新动向(2013年8月,#07;星期三,28日)" 中提到:
顺便提一下,使用覆盖通常的“必须快进”的推送是使用在“next”分支上开发的“force-with-lease”选项完成的,如下所示:
$ 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

注意:"git push --force-with-lease"已经被教导,如果需要强制推送(或快进),则会报告。因此,该命令在其输出中更加详细,适用于git 2.8(2016年3月)。
引用:

修复--force-with-lease的参考状态报告

--force--with-lease推送选项比--force提供了较少的状态信息。
特别是,即使进行了强制更新,输出也表明参考已快进。


注意那个选项被忽略或绕过的情况,如在Git 2.13(2017年第二季度)中解释


在使用--force参数后,其他人可以很好地恢复:https://dev59.com/D2855IYBdhLWcg3w6IzV#20423029 - VonC

19
你可以尝试使用 git push --force 命令来强制推送。
--force

通常情况下,该命令会拒绝更新不是本地引用祖先的远程引用,被用来覆盖它。此标志禁用检查。
这可能会导致远程存储库丢失提交;请谨慎使用。
因此,如果许多人已经从源头拉出同一个分支,那么这可能会在他们这一侧引起一些rebase issue问题。
可以在服务器端阻止该操作,正如ebneter在评论中指出的那样:
根据远程配置的不同,这可能无法正常工作。
我的所有中央存储库都配置为receive.denyNonFastForwards = truereceive.denyDeletes = true,在这种情况下,任何此类手术都必须在远程服务器上完成。
然而,在GitHub的情况下,用户管理其GitHub存储库时这些设置并不容易获得
因此,如果您错误地执行了git push --force,那么您所剩下的就是向GitHub支持提出申请,让他们检查本地(即“GitHub”)reflogs,看看是否可以恢复旧提交。
(由于reflogs是本地的,就像我最近被记住的那样。因此,在push --force期间由新提交替换的提交仅在 GitHub 服务器端尚未进行'git gc'或'git prune'的情况下仍可见)

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

这可能会使其他贡献者的本地repo混乱不堪,如果您强制推送,则有时只是必要的恶行(在使用Git的生命周期中,我可能必须做过两次)。


@Marco:没错。虽然它必须小心使用(例如参见http://support.github.com/discussions/repos/3240-how-to-restore-previous-version-of-repository)。 - VonC
@ebneter:但是我们正在谈论的是GitHub;它似乎没有提供这种服务器端设置:http://support.github.com/discussions/feature-requests/397-per-repository-option-to-disable-git-push-force-enable-receivedenynonfastforwards - VonC
啊,我没看到这是 GitHub。不过,这个总的来说还是需要注意的。 - ebneter
正确的 - 就像VonC所说的那样 - 如果你强制推送,这可能会真正破坏其他贡献者的本地仓库 - 虽然有时这是必要的恶(在我使用Git的生命周期中,我可能只做过两次)。 - Marco Ceppi
@VonC:非常好。GitHub 不允许您以那种方式进行配置,这有点奇怪。 - ebneter
显示剩余3条评论

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接