如何正确地强制Git推送?

我已经设置了一个远程非裸机“主”存储库并将其克隆到我的计算机上。我做了一些本地更改,更新了我的本地存储库,并将更改推送回我的远程存储库。到那时为止,一切都很好。

现在,我必须在远程存储库中更改一些内容。然后我在本地存储库中更改了一些内容。我意识到不需要对远程存储库进行更改。所以我尝试从本地存储库到远程存储库git push,但我遇到了一个错误,例如:

为了防止您丢失历史记录,请使用非快进更新拒绝在再次推送之前合并远程更改。请参阅注释关于git push --help的快进部分的详细信息。

我想那可能是

git push --force

它确实会强制更新,但是当我回到远程存储库并进行提交时,我注意到文件包含过时的更改(主远程存储库以前的更改)。

正如我在对其中一个答案的评论中提到的:

[我]尝试强制,但是当返回主服务器保存更改时,我的分期过时了。因此,当我提交存储库时不一样。当我再次尝试使用git ush时,我得到了同样的错误。

如何解决此问题?

2003358 次浏览

首先,我不会直接在“主”存储库中进行任何更改。如果你真的想拥有一个“主”存储库,那么你应该只推到它,永远不要直接更改它。

关于你得到的错误,你是否尝试过从本地存储库git pull,然后从主存储库git push?你目前正在做的(如果我理解得很好)是强制推送,然后在“主”存储库中丢失你的更改。你应该首先在本地合并更改。

只要做到:

git push origin <your_branch_name> --force

或者如果您有特定的repo:

git push https://git.... --force

这将删除您之前的提交并推送您当前的提交。

这可能不合适,但如果有人偶然发现这一页,认为他们可能想要一个简单的解决方案…

短旗

还要注意-f--force的缩写,所以

git push origin <your_branch_name> -f

也将工作。

如果push --force不起作用,你可以做#1。看看这个例子上的2nd行:

git reset --hard HEAD~3  # reset current branch to 3 commits agogit push origin master --delete  # do a very very bad bad thinggit push origin master  # regular push

但当心…

永远不要回到公共git历史上!

换句话说:

  • 永远不要force推送公共存储库。
  • 不要做这件事或任何可能打破某人pull的事情。
  • 永远不要resetrewrite历史在回购有人可能已经拉。

当然,即使是这个规则也有非常罕见的例外,但在大多数情况下,它不需要这样做,它会给其他人带来问题。

做一个恢复。

始终要小心你推送到公共回购的内容。恢复:

git revert -n HEAD~3..HEAD  # prepare a new commit reverting last 3 commitsgit commit -m "sorry - revert last 3 commits because I was not careful"git push origin master  # regular push

实际上,两者源HEAD(来自恢复邪恶重置)将包含相同的文件。


编辑以添加更新的信息和push --force周围的更多参数

考虑使用租赁而不是推送来推送,但仍倾向于恢复

push --force可能带来的另一个问题是,当有人在你之前推送任何东西,但在你已经获取之后。如果你现在推送强制你的重新版本,你将取代别人的工作

git1.8.5中引入的git push --force-with-lease(对问题的感谢@VonC注释)试图解决这个特定问题。基本上,如果远程自上次获取以来被修改,它会带来错误并且不会推送。

如果你真的确定需要push --force,但仍然想防止更多的问题,这是很好的。我甚至认为它应该是默认的push --force行为。但它仍然远远不能成为强迫push的借口。在你的rebase之前的人仍然会有很多麻烦,如果你有恢复,这是很容易避免的。

既然我们谈论的是git --push实例…

为什么会有人想要强迫?

@林奇在评论中带来了一个很好的推送示例:敏感数据。你错误地泄露了不应该推送的数据。如果你足够快,你可以通过在顶部强制推送来“修复”*它。

*数据仍将在遥控器上除非你也做垃圾收集器把它弄干净。它也有明显的潜力被已经的人传播,但你明白了。

如果我在本地分支A上,并且我想强制将本地分支B推送到源分支C,我可以使用以下语法:

git push --force origin B:C

这是我们在维护历史记录的同时替换公司gitHub存储库上的master的解决方案。

push -f to master在公司存储库上经常被禁用以维护分支历史记录。这个解决方案对我们有用。

git fetch desiredOrigingit checkout -b master desiredOrigin/master // get origin master

git checkout currentBranch  // move to target branchgit merge -s ours master  // merge using ours over master// vim will open for the commit messagegit checkout master  // move to mastergit merge currentBranch  // merge resolved changes into master

将您的分支推到desiredOrigin并创建PR

使用以下命令:

git push -f origin master

我也有同样的问题,但最终还是解决了。你最有可能需要做的是运行以下两个git命令(用git提交修订号替换哈希):

git checkout <hash>git push -f HEAD:master

如果您使用Github访问令牌进行身份验证,请尝试以下操作:

  • git remote set-url origin https://YourTokenNum@github.com/UserName/ProjectName

  • git push --force --set-upstream origin master

我的问题是——我做到了:

git checkout arbitrary_commitgit push origin master --force

这不是正确的做法。相反,我不得不:

git reset HEAD~3git push origin master --force

注意:数字3只是一个例子。您应该输入自己的数字。

git推送-f起源:这将在签入存储库中进行硬推送。

git push --force可以完成这项工作,尽管git push --force-with-lease是一个更安全的命令

git push --force覆盖远程分支,而git push --force-with-lease仅在您的本地副本知道远程分支上的所有提交时覆盖远程分支。这种差异使得在项目上销毁其他人的更改变得更加困难。