无论如何撤消git push -f?

时间:2013-01-23 09:26:31

标签: git

如果我使用push -f重叠最后一次提交,即A,在远程存储库上,其他人在推送之前已经拉了A。

无论如何要撤消这种情况,以免给别人带来麻烦?

对于push -f一个原始的“假装”没有触及任何内容,它是否有用?

或者

git如何决定本地仓库是否偏离远程跟踪?

1 个答案:

答案 0 :(得分:34)

有几种方法可以在推送之前找到原始HEAD(ORIG_HEAD可能不是其中之一):

终端回滚

如果你足够幸运地让终端打开,那么推送时会有一些输出,如下所示:

...
To user@host:repo.git
 + abcdef0...1234567 HEAD -> branchname (forced update)

此处,abcdef0是之前的HEAD(您的A),1234567是您强迫它的目的。

git reflog

git reflog的输出告诉您所做事情的时间顺序历史。您基本上想要返回有问题的行(在更改之前已经检出了您的分支)并从第一列中获取提交ID。

这里最有用的命令是git reflog show remotes/origin/branchname。这应该显示您的强制更新(1234567)和之前的提交ID(abcdef0)作为前两行。

以前的参考

这里有几个提交引用可能很有用:

  • @{1}(或branchname@{1},如果您不在该分支上)是该引用的先前值。仅在您未对本地分支机构进行任何其他提交时才有效。
  • 同样,remotes/origin/branchname@{1}将是遥控器上ref的先前值。仅在其他人没有推到遥控器时才有效。

检查您是否拥有正确的ID

如果您想确认您从上述某种方法获取的ID是否正确,只需查看它:

git checkout abcdef0

并环顾四周。如果git log看起来很熟悉(我还建议使用tig来浏览您的存储库,并且您甚至可以运行tig abcdef0来查看给定提交的日志),那么您可以确信你正在重新找回正确的地方。

重置为先前状态

获得之前的提交ID后,您可以重置为该ID并再次强制推送:

git checkout branchname # if you're not on it already
git reset --hard abcdef0
git push -f

或只是:

git push -f origin abcdef0:branchname

这会将分支的状态恢复到强制推送之前的状态。 (快速注意:第一个片段将更新您的本地分支以及遥控器;第二个片段仅更新遥控器。)

有什么影响?

如果你强行推动人们已经拉动了分支,如果你强行推回原来那么他们将在随后更新时遇到问题。如果他们没有对该分支进行任何提交,他们可以删除他们的本地分支并重新签出(在git fetch之后确保他们有最新的引用),或者以下将执行同样的:

git fetch
git checkout branchname # if you're not on it already
git reset --hard origin/branchname

如果他们已经进行了本地提交,那么他们需要将这些更改重新定义到正确的历史记录中(并可能解决任何冲突):

git fetch
git checkout branchname # if you're not on it already
git rebase --onto origin/branchname 1234567

以上意思是“在1234567(正确的头部)之上重播origin/branchname之后的所有提交(不正确的头部)。”

相关问题