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


1271

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

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

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

我以为

git push --force

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

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

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

如何解决此问题?


4
您很快就会(2013年第4季度git1.8.5)能够做得git push -force更加谨慎
VonC


6
正如我在自己的答案中详述的那样git push --force确实是强制推送的另一种有效方法,它将推送分支git push origin master --force与使用Git的默认设置一样好push.default config settings,尽管在2.0之前和2.0之后的Git版本中,专门推送的分支有所不同。

2
git push --force这些天工作正常,FWIW ...
rogerdpack '18

git push --force-with-lease效果更好:),除非您期望的状态,否则它将拒绝更新分支。(见developer.atlassian.com/blog/2015/04/force-with-lease
spoorcc

Answers:


2304

做就是了:

git push origin <your_branch_name> --force

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

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

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

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

短旗

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

git push origin <your_branch_name> -f

也可以。


58
您可以git push origin +master改用,这样就可以在不强制所有引用的情况下推送多个引用。
nickgrim

5
请注意,如果您不小心只是执行了操作git push --force,则可能会弄乱您的master分支(取决于您的推送默认行为)。可能会很糟..:D
Jeewes 2014年

9
@Jeewes从Git 2.0版开始,默认的行为git push --force基本上是强制将当前已签出的分支推送到其远程计数器部分,因此,如果您已将master分支签出,则它与相同git push origin master --force。如果您使用的matching设置会有所不同push.default,这是2.0之前的Git版本的默认设置。matching所有本地分支推送到具有相同名称的远程分支,因此强行推送绝对可能不是您想要的...

@Jeewes但是在Git 2.0中,默认设置更安全,或者至少没有比git push origin master --force现在更危险的了。

2
push -f很好,但对于主服务器而言则不建议这样做,因为大多数公司存储库都对主服务器禁用了-f。该merge -s ours工作对我来说
米哈伊

247

如果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
  • 永远不要reset或有人可能已经拉rewrite回购中的历史记录。

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

请还原。

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

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-leasegit 1.8.5中引入(感谢@VonC对问题的评论)试图解决此特定问题。基本上,如果自从您最近一次获取以来修改了遥控器,它将带来一个错误并且不会推送。

如果您确实确定push --force需要a,但仍然希望防止出现更多问题,那么这很好。我要说的应该是默认push --force行为。但这绝不是强迫一个借口的借口push。谁的人获取你的前底垫中仍然有很多的烦恼,可能你已经很容易地避免的恢复来代替。

既然我们在谈论git --push实例...

为什么有人要强迫推?

@linquize在评论中带来了一个很好的推动力示例:敏感数据。您错误地泄漏了不应推送的数据。如果速度足够快,则可以通过强行推顶来“修复”*它。

*数据仍然会在遥控器上,除非你同时做垃圾回收,或以某种方式进行清洁。还有它是由其他人谁愿意传播的明显的潜在获取它了,但你的想法。


1
如果可行,@ rogerdpack并不是问题。它是。但这可能会带来巨大的灾难。有人做的越多(强制推送),而您从公共仓库进行更新(拉)的次数越少,灾难就越大。它可以摧毁您所知道的世界!!! 111至少是由该特定存储库组成的世界。
cregox

3
如果你有敏感数据,力推它
linquize

3
@Cawas:我认为他的意思是,如果您试图从存储库中删除敏感数据,那么您重写历史记录。如果还原,则敏感数据在较早的提交中仍然存在。也就是说,如果其他人已经从存储库中拉出了记录,那么重写历史记录将无法帮助您阻止他们访问敏感数据-那时已经太晚了。
Stuart Golodetz

3
git push origin master --delete # do a very very bad bad thing git push origin master # regular push这实际上完美地解决了我的问题(仅在我和我的朋友的回购中)。也许对于公共回购是错误的,但是对于私人回购来说,这可以挽救生命。
CanPoyrazoğlu2014年

1
这种情况在某些回购管理器,aka自动压缩等情况下会自动发生。在完成功能分支以减少提交后强制推送是很常见的现象。
FlavorScape

18

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

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


是的,我尝试过一次拉动,但是由于这种拉动,我正在丢失数据。我想使我的主存储库像我的本地存储库一样,而无需先从主存储库进行更新。
Spyros

1
在这种情况下,请使用git push -f,但是如果再次更改主存储库,则必须返回到本地存储库和git pull,以便它与最新更改保持同步。然后,您可以完成工作,然后再次推动。如果遵循此“推拉”工作流程,则不会得到您抱怨的那种错误。
2011年

是的,我知道这是我的错:/我会尝试一下,然后再过一趟thanx
Spyros

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

17

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

git push --force origin B:C

2
我发现即使我在本地B分支机构,也仍然需要这样做git push --force origin B:C。就我而言,git push --force origin C无论我当前在哪个分支上,它似乎只会从本地主服务器推送到远程C分支。 git version 2.3.8 (Apple Git-58)
曾伟石

12

使用以下命令:

git push -f origin master

1
也许可以给出更多关于此答案为什么比其他答案更可取的解释,以及使它与众不同的原因。
亚当

抱歉,给您带来不便,我遇到了同样的问题,此命令已解决,我想我应该分享一下。
mustafa Elsayed

12
它和其他的一样,只是改变了-f国旗的位置……
svelandiag

11

我真的建议您:

  • 只推送到主仓库

  • 确保主存储库是裸存储库,以免主存储库工作树与其.git基础不同步而不会出现任何问题。请参阅“ 如何将本地git存储库推送到另一台计算机?

  • 如果您确实必须在主(裸机)存储库中进行修改,请克隆它(在主服务器上),进行修改然后将其回推

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


5

这是我们在维护历史记录的同时替换公司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


3

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

git checkout <hash>
git push -f HEAD:master
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.