如果我使用push -f
重叠最后一次提交,即A,在远程存储库上,其他人在推送之前已经拉了A。
无论如何要撤消这种情况,以免给别人带来麻烦?
对于push -f
一个原始的“假装”没有触及任何内容,它是否有用?
或者
git如何决定本地仓库是否偏离远程跟踪?
答案 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是否正确,只需查看它:
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
之后的所有提交(不正确的头部)。”