如何正确强制执行 Git 推送?

我已经建立了一个远程的非裸露的 “主” 仓库,并将其克隆到我的计算机上。我进行了一些本地更改,更新了本地存储库,然后将更改推回到远程仓库中。到那时为止一切都很好。

现在,我不得不更改远程仓库中的某些内容。然后,我更改了本地存储区中的某些内容。我意识到不需要更改远程仓库。所以我尝试将本地存储库中的git push送到远程存储库中,但是出现类似以下错误:

为了防止丢失历史记录,拒绝了非快进更新,请在合并之前合并远程更改。有关详细信息,请参见git push --help的 “关于快进的说明” 部分。

我以为

git push --force

会强制我的本地副本将更改推送到远程副本,并使其相同。 它确实强制执行更新 ,但是当我返回到远程存储库并进行提交时,我注意到文件包含了过时的更改(主要远程存储库以前具有的更改)。

正如我在对答案之一评论中提到

[我] 尝试强制执行,但是当回到主服务器以保存更改时,我得到了过时的暂存。因此,当我提交存储库时,它们是不一样的。当我再次尝试使用 git push 时,出现相同的错误。

如何解决此问题?

答案

做就是了:

git push origin <your_branch_name> --force

或者,如果您有特定的仓库:

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

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

可能不合适,但是如果有人偶然发现此页面,以为他们可能想要一个简单的解决方案...

短旗

另请注意, -f--force缩写,因此

git push origin <your_branch_name> -f

也可以。

如果push --force不起作用,您可以执行push --delete 。查看此实例的第二行:

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

但是要当心...

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

换一种说法:

  • 永远不要force推动公共存储库。
  • 请勿执行此操作或执行任何可能破坏某人pull
  • 永远不要在可能已经拉过的仓库中 resetrewrite历史记录。

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

请还原。

始终谨慎对待您要公开回购的内容 。还原:

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

实际上, 两个原始 HEAD(来自revert和来自邪恶的 reset )都将包含相同的文件。


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

考虑使用租约推力而不是推力,但仍希望还原

push --force可能带来的另一个问题是,有人在您执行任何操作之前但在您已取回操作之前进行了任何操作。如果您现在强制您重新设置版本,则您将替换其他人的工作

git push --force-with-lease 1.8.5 中引入的git push --force-with-lease感谢 @VonC对问题的评论)试图解决此特定问题。基本上,如果自从最近一次获取以来修改了遥控器,它将带来一个错误并且不会推送。

如果您确实确定需要push --force这很好,但是仍然希望防止出现更多问题。我要说的应该是默认的push --force行为。但这仍然不是强迫push的借口。在您恢复 基准之前拿到钱的人仍然会遇到很多麻烦,如果您转而恢复 ,则可以轻松避免。

由于我们在谈论git --push实例...

为什么有人要强迫推?

@linquize在评论中带来了一个很好的推动力示例: 敏感数据 。您错误地泄漏了不应推送的数据。如果你足够快,你可以“修复” *这会强制在上面一推。

*除非您也进行垃圾收集以某种方式清除它 ,否则数据仍将位于远程上 。它也很可能被已经拿来的其他人传播,但是您明白了。

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

关于您遇到的错误,您是否尝试git pull本地存储库进行git pull ,然后将git push到主存储库?您当前正在执行的操作(如果我理解得很好)是强制执行该操作,然后丢失 “主” 存储库中的更改。您应该首先在本地合并更改。

如果我在本地分支 A 上,并且要强制将本地分支 B 推到原始分支 CI,则可以使用以下语法:

git push --force origin B:C

我真的建议您:

换句话说,请确保从主服务器和本地计算机都可以访问裸仓库,以使单个上游仓库可以从中 / 从中进行拉取 / 拉取。

使用以下命令:

git push -f origin master

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

经常禁用push -f来掌握公司存储库,以维护分支机构的历史记录。该解决方案为我们工作。

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

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

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

我有同样的问题,但终于明白了。您最可能需要做的是运行以下两个 git 命令(用 git commit 修订号替换哈希):

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