“Git push非快进更新被拒绝”是什么意思?

168
我使用Git管理我的两台计算机和开发。我试图将更改提交到GitHub,但出现了以下错误: “无法推送一些引用至。为了防止您丢失历史记录,拒绝了非快进式更新。请合并远程更改后再次推送。” 这是什么原因,我该如何解决? 编辑: 拉取库返回以下内容: *分支 master->master (non-fast-forward) 已经是最新的 尝试推送仍然给我上述错误。

请参阅Git非快进拒绝 - user456814
9个回答

154

GitHub有一个名为"处理“非快进”错误"的很好的部分。

起初,这个错误可能会让人感到有些压抑,不要害怕。
简单来说,如果没有丢失提交,git无法在远程进行更改,因此拒绝推送.
通常情况下,这是由另一个用户向同一分支推送导致的。您可以通过获取并合并远程分支或使用pull一次性执行两个操作来解决此问题。

在其他情况下,此错误是通过使用如git commit --amendgit rebase等命令在本地进行破坏性更改而导致的。
虽然您可以通过将--force添加到push命令来覆盖远程内容,但只有在您完全确定要这样做时才应该这样做。
强制推送可能会对已获取远程分支的其他用户造成问题,并被认为是不良实践。 如果有疑问,请不要强制推送


Git不能像快进合并一样在远程进行更改,Visual Git Reference将其描述如下:

alt text

虽然这不是完全符合您的情况,但可以帮助您了解什么是“快进”(其中一个分支的HEAD简单地移动到新的更近提交)。


"branch master->master(非快进)已经是最新的"通常是针对不跟踪其远程副本的本地分支。
例如,请参见此SO问题 "git pull says up-to-date but git push rejects non-fast forward"。

或者这两个分支已经连接,但它们各自的历史记录存在不同:
请参阅“Never-ending GIT story - what am I doing wrong here?”。

这意味着您的Subversion分支和远程Git主分支在某些方面存在不一致。
在其中一个中提交了某些更改,而在另一个中则没有相应的更新。
运行gitk --all命令,它应该会给你一些线索,帮助你找到错误所在——查看历史记录中的“分叉”。


59

这意味着远程仓库中已经有其他与您的提交不同的提交。通常可以使用

解决此问题。

git pull

在你执行推送操作之前

最终,“快进”意味着提交可以直接应用于工作树,而不需要合并。


4
这是对我有效的方法!我忘记了在代码库网站上更改了readme.md文件! - ryanwinchester

16

在这种情况下,您可能需要使用强制推送操作

git push origin master --force


2
这是错误的。Github的全部源代码将被删除,只有您的新源代码将被推送,旧的源代码将被删除。 - logeshpalani31
5
小心使用 --force 的副作用。 - Miles Erickson

14

快进式更新是指另一侧最新提交之后,仅该侧有更改,因此不需要合并。这意味着您需要在推送之前合并您的更改。


11

不要使用 git -f 来进行 push 操作,因为这可能会导致之后灾难性的后果。

你只需要对本地分支执行 git pull 命令。

例如:

git pull origin 'your_local_branch'

然后执行git push


2
如果您的远程分支已更新但未与本地存储库同步,也可能会出现这种情况。在我的情况下,我创建了一个git存储库并添加了readme文件。在我的本地机器上,我创建了要上传到该存储库中的新文件,因此我尝试按照通常的方式推送。之后,我执行了$ git pull,但它抛出了fatal: refusing to merge unrelated histories错误(在bash中作为普通文本显示)。 我尝试了重新基础、重新暂存和重新提交,但问题仍未解决。在这种情况下,我的目标是无论如何都要合并它,因为我想保留两者,并且它们之间没有任何共同的文件。因此,我通过传递以下参数允许不相关的历史记录:

$ git pull origin main --allow-unrelated-histories

此命令将合并-忽略它们位于不同位置的事实。

然后使用以下命令将其推送到origin分支: $ git push -u origin main

如果有人更擅长解释这一点,请随意编辑此答案。


0

在将更改推送到远程仓库/分支之前,您需要合并和解决本地的冲突。

1)拉取(获取和合并)

$ git pull remote branch 

2) 推送更改

$ git push remote branch 

你仍然可以通过使用--force选项强制进行push,但应该避免这样做,因为它可能会导致更改丢失或对其他贡献者产生不良影响。


0
在我的情况下,对于完全相同的错误,我并不是唯一的开发人员。
因此,我同时提交和推送了我的更改,在“提交”对话框弹出窗口的底部看到:

Checked option for: Push changes immediately to origin

...但我犯了一个巨大的错误,忘记点击Fetch按钮查看最新版本,结果我没有看到。

提交成功执行,但是没有推送,而是出现了同样的错误; 即使其他开发人员没有更改与我相同的文件,我也无法拉取最新版本,因为同样的错误被呈现。

图形用户界面解决方案

大多数时候,我更喜欢使用Sourcetree的GUI(图形用户界面)。这个解决方案可能不是理想的,但这是让我重新开始而不必担心可能会丢失我的更改或妥协其他开发人员的更新的方法。

步骤1

右键单击你之前提交的提交以撤消本地提交的更改,并选择Reset current branch to this commit,如下所示:

Sourcetree window with right-clicked commit and selecting: Reset current branch to this commit

步骤二

当所有的加载图标消失并且Sourcetree已经完成上一个提交的加载时,在窗口左上角,单击Pull按钮...

Sourcetree window with with the Pull button highlighted

...然后会弹出一个对话框,点击右下角的确定按钮:

Sourcetree window dialog popup with the OK button highlighted

步骤三

拉取最新版本后,如果没有出现任何错误,请跳过步骤四(下一步)。否则,如果您在此时发现任何合并冲突,比如我在Web.config文件中遇到的情况:

Sourcetree window showing the error hint: Updates were rejected because the tip of your current branch is behind

...然后点击顶部的Stash按钮,会弹出一个对话框,您需要编写一个描述性名称来说明您的更改,然后点击OK按钮:

Sourcetree window with Stash button highlighted and dialog popup showing input to name your stash with OK button highlighted

...一旦Sourcetree完成了你修改文件的暂存,重复步骤2(上面的先前步骤),然后你的本地文件就会有最新更改。现在你可以通过打开Sourcetree左列底部看到的STASHES来重新应用你的更改,使用箭头展开暂存,然后右键选择Apply Stash '描述你的更改名称',然后在弹出的对话框中选择OK按钮:

Sourcetree window with the Stashes section expanded and changes right-clicked with Apply Stash highlighted

Sourcetree dialog popup ask your to confirm if you would like to apply stash you your local copy

如果你现在有任何合并冲突,请前往你偏好的文本编辑器,如Visual Studio Code,在受影响的文件中选择 接受传入的更改 链接,然后保存:

enter image description here

然后回到Sourcetree,在顶部点击Commit按钮:

enter image description here

然后右键单击冲突的文件,并在“解决冲突”下选择“标记为已解决”选项。

enter image description here

步骤4

终于!!!我们现在可以提交我们的文件,还要在点击“提交”按钮之前勾选“立即将更改推送到源”的选项:

enter image description here

顺便说一下,写这篇文章的时候,我刚要提交代码时,另一个开发人员已经提交了一次,所以我不得不重复之前的步骤。


0

关于我的回答,可以参考这里... Git push失败,"非快进式更新被拒绝"


最安全的解决方法是使用 --rebase

例如:

git pull <remote> <branch> --rebase

这可能会导致本地分支冲突,您需要手动解决它们。
一旦您解决了所有冲突,就可以使用 --force-with-lease 推送更改。
例如:
git push <remote> <branch> --force-with-lease

使用此标志,Git 将检查分支的远程版本是否与您正在 rebase 的版本相同,即如果有人在您 rebase 时推送了新的提交,则该推送将被拒绝,您将被强制重新 rebase 分支。

如果您正在处理每小时数百个提交的大型项目,则这很烦人,但仍然是解决此问题的最佳方法。

除非您确切知道自己在做什么,否则请避免使用 --force

使用 --force 是具有破坏性的,因为它会无条件地用本地内容覆盖远程存储库。

但是使用 --force-with-lease,可以确保不会覆盖其他人的工作。

在 Atlassian 的开发者博客中阅读此文章以获取更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接