我该如何处理这个 Git 警告?“不指定如何协调分歧分支就进行拉取是不被鼓励的”。

1251

在执行git pull origin master命令之后,我收到了以下信息:

warning: Pulling without specifying how to reconcile divergent branches is
discouraged. You can squelch this message by running one of the following
commands sometime before your next pull:

  git config pull.rebase false  # merge (the default strategy)
  git config pull.rebase true   # rebase
  git config pull.ff only       # fast-forward only

You can replace "git config" with "git config --global" to set a default
preference for all repositories. You can also pass --rebase, --no-rebase,
or --ff-only on the command line to override the configured default per
invocation.

remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), 51.49 KiB | 850.00 KiB/s, done.

拉取似乎成功了,但我不确定。

我该怎么办才能解决这个问题?


89
请提交一个缺陷报告,指出警告信息令人困惑。应该添加一个“推荐”的选项,并且只有在请求时才显示警告,而不是因为版本更改而自动显示。许多自动脚本可能会因此意外行为而出现故障。 - Wolfgang Fahl
2
@Qumber - 感谢您的评论。例如,Crontab条目将在出现未经过滤的输出或可以使用简单grep过滤的输出时开始发送电子邮件。意外的输出可能会产生各种副作用。 - Wolfgang Fahl
2
@WolfgangFahl,每次拉取通常都会有一些不同的输出。因此,任何仅依赖于此的脚本可能都编写得很糟糕。此外,不应在没有进行广泛测试的情况下升级生产环境。我更喜欢根本不升级生产环境。相反,我会创建一个新实例,使用最新的所有内容托管我的应用程序,在那里测试所有内容,然后将其投入生产。 - Qumber
1
我收到了这条消息,奇怪的是它似乎是由 VS Code 引起的。当我在终端中输入 git push 时,我的代码被顺利推送了。 - MikhailRatner
1
像 @MikhailRatner 一样,我在终端中使用 git push 没有任何问题。如果有人在 VS Code 中遇到这个问题,我建议尝试这个解决方案。 - Paweł Mioduszewski
显示剩余6条评论
36个回答

1128
在默认模式下,git pull 是 git fetch 后跟着 git merge FETCH_HEAD 的简写。 当你执行 git pull origin master ,git pull 会执行一个合并操作,通常会创建一个合并提交。因此,默认情况下从远程拉取代码不是一项无害的操作:它可能会创建一个之前不存在的新的提交 SHA 哈希值。这种行为可能会使用户混淆,因为看起来应该是一项无害的下载操作实际上以不可预测的方式更改了提交历史记录。 为了避免这种情况发生,你需要:
git pull --ff-only

(还是不用?继续阅读以了解哪个适合您的要求)

使用 git pull --ff-only,Git 只会在不创建新提交的情况下“快进”更新您的分支。如果无法完成此操作,则 git pull --ff-only 会简单地中止并显示错误消息。

您可以配置 Git 客户端始终默认使用 --ff-only,这样即使您忘记命令行标志,也可以获得此行为:

git config --global pull.ff only
注意:使用--global标志将更改应用于您机器上的所有存储库。如果您只想在当前存储库中使用此行为,请省略该标志。 摘自这里

这个警告是在Git 2.27中添加的。

完整的警告如下:

不指定如何协调分歧分支就进行拉取操作是不鼓励的。您可以通过运行以下命令之一来消除此消息:

git config pull.rebase false     # 合并(默认策略)
git config pull.rebase true      # 变基
git config pull.ff only                # 仅快进

您可以将“git config”替换为“git config --global”,以设置所有存储库的默认首选项。您还可以在命令行上传递--rebase、--no-rebase或--ff-only,以覆盖每次调用的配置默认值。

该警告提供了三个命令作为选项,所有这些命令都将抑制警告。但它们具有不同的目的:

git config pull.rebase false     # merge (the default strategy)

这将保持默认行为并抑制警告。

git config pull.rebase true      # rebase

这实际上是在远程分支的基础上提交,保持本地和远程的单一分支(与默认行为不同,在默认行为中涉及两个不同的分支 - 一个在本地,另一个在远程 - 并且要合并这两个分支,需要执行合并操作)。

git config pull.ff only          # fast-forward only

只有在本地分支可以快进时,才会执行此操作。如果不能快进,则会显示错误消息并中止操作(不会创建任何提交)。


更新1:

如果您使用的是Git 2.29或更高版本,现在可以将pull.ff设置为falsetrueonly,以消除警告。

git config pull.ff true

true - 这是默认行为。如果可能,拉取将进行快进,否则它将被合并。

git config pull.ff false

false - 拉取操作永远不会快进,而总是创建一个合并。

git config pull.ff only

only - 如果可能,Pull 操作会快进,否则会中止并显示错误信息。


更新2:
在版本2.35之前,这个新实现的功能存在一个bug,即使用户使用了git pull命令中的三个标志之一,Git也会显示此警告。现在已经修复了这个问题,请考虑将您的Git更新到版本2.36或更高版本。


注意:

  • 阅读这篇非常好的回答,作者是torek,可以更清楚地了解幕后发生了什么,并了解哪个选项是最合适的。

  • 您可能需要关注VonC此处答案,以了解将来更新中对该功能所做的更改。


505
我感激您花费时间和精力回答问题,但坦率地说,这仍然让我完全无法理解。 - Jared Nedzel
11
此处所评论,这个警告不受分支是否实际上分叉的影响。最初的“Your branch is probably diverging.”可能是误导性的。 - Joe
7
我必须说,信息中提供的三个选项对于我来说都没有成功地抑制该信息。然而在这里的答案 (git config --global pull.ff only) 却成功了。 - DiskJunky
5
谢谢您的回答,帮了我很多。我只使用功能分支进行工作,在我的开发分支上没有本地更改。因此,默认设置对我来说非常适用。但是如果我使用了pull.ff并出现冲突,我该如何解决这个问题?如果ff不可行怎么办? - CanO
3
这是一个非常好的解释。我之前在拉取代码时也遇到了这种意外行为。对我来说,当我还在本地的一个功能分支上时使用 git pull origin main 来更新主分支时(我忘记先在本地切换到主分支),它最终拉取了远程主分支的更改并将其合并到我的功能分支中。ff 策略似乎更安全。 - Matt Welke
显示剩余19条评论

227

以下是在Git 2.27中新增的警告信息:added

 * "git pull" issues a warning message until the pull.rebase
   configuration variable is explicitly given, which some existing
   users may find annoying---those who prefer not to rebase need to
   set the variable to false to squelch the warning.
为了消除警告,请将以下建议值之一设置为您首选的默认行为,以用于在命令行上未指定特定行为的情况下进行 git pull(使用 --ff、--no-ff、--ff-only、--rebase)。在所有情况下,如果可能的话,git 将尝试快进合并(什么是 Git 快进合并?请参见这里)。这些设置控制当您的分支中存在但不在远程分支中时发生的情况。
  git config pull.rebase false  # merge (the default strategy)

这是现有的默认行为;将其设置为无警告,且不改变行为; git 将远程分支合并到您的本地分支。

  git config pull.rebase true   # rebase

这里,git将尝试在远程分支上重新应用您的更改。有关为什么可能需要这样做的更多详细信息,请参见什么时候应该使用git pull --rebase?

  git config pull.ff only       # fast-forward only
如果无法进行快进合并,git将拒绝继续操作。正如git pull --rebase和git pull --ff-only的区别所述:

除非当前HEAD已经是最新的或者合并可以被解决为快进合并,否则拒绝合并并以非零状态退出


65
这实际上是最正确的答案,因为它解释了为什么像我这样的人在使用git近十年后突然看到这个警告。然而,如果能提供一些关于所提供选项的指导将会很有用。例如,指出将pull.ff设置为“only”不会阻止您执行“pull --rebase”覆盖它。 - kdopen
2
@tekumara 请查看 https://dev59.com/ZW435IYBdhLWcg3woRnG#15935584 - Joe
7
如果你的分支有变更但在远程分支中不存在,那么看起来 Git 只应在这种情况下抛出警告。如果我正在拉取我的主干(并且主干被正确地使用),那么我不需要担心这个问题。 - Keith Tyler
10
@Joe 我喜欢你的回答,认为它是正确的答案,但是无论git是否实际上已经执行了任何操作,都会看到这个信息。我认为发出此警告的正确时机是在git必须执行某些操作时,然后应该以此消息失败。不要只是在一开始就向用户发送此消息。又是一件让我对git爱恨参半的事情。 - Jon V
2
Joe,谢谢你的回答,帮了我很多。我不确定ff-only标志是什么意思。如果启用了ff-only并且git pull失败了,那么怎么办?此时必须手动执行合并或变基才能取得任何进展。因此,如果目标是避免混乱的依赖关系图,这并没有改变任何事情——无论如何,自动或手动,您的依赖关系图最终都会变得混乱。我想,如果必须手动执行,则可以更好地控制它。但是我猜通常人们不知道如何避免混乱,就像Git本身一样。 - Robert Dodier
显示剩余3条评论

88

运行此命令:

git config pull.ff only

祝贺你能够继续工作。


130
致命错误:无法快速前进,操作已中止。 - y_159
53
也许对你来说已经太晚了,但对其他人有用。为了解决“致命错误:不可能快进,中止”警告,我使用了git pull origin <branch> --rebase。我还注意到我没有设置上游,在第一次推送时我加了-u,例如git push -u origin <branch> - Vinícius Cerqueira Bonifácio
2
@ViníciusCerqueiraBonifácio 我通常会遇到这个错误,最后我只能执行 git pull --no-ff。我会尝试你的建议。 - y_159
3
这并没有解释它的作用,只会在后续出现无法使用ff时造成更多问题,而经验不足的用户将不知所措。此外,这种非默认行为将更难以调试。 - Martino
git config pull.ff only 对我很有用;在我恢复推送之前需要 git pull - Graham John
我遇到了同样的问题:致命错误:无法快进,中止。整个事情都是个谜:我是唯一一个克隆过存储库的人,也是唯一一个向其推送过内容的人,而且只在一个目录下操作。到底发生了什么? - undefined

78

git pull origin main --rebase

这对我有用!


7
一样的情况。如果你在远程仓库上刚提交了一个代码,但是在本地提交其他代码之前忘记先拉取,但没有冲突,那么这个简单的变基操作就可以解决问题。 - Caique C Pereira
我同意 https://stackoverflow.com/users/8991247/caique-c-pereira。 - Ghulam Akbar
我之后有很多冲突 :( - Vitaly Zdanevich
这就是方法,你不会修改远程的其他新提交。而且世界不需要知道你的本地提交,所以你可以随意修改和更改其哈希值。 @VitalyZdanevich 当然你可能会遇到合并冲突,无论如何你都必须处理它。你期望怎样呢? - undefined

55
如果您正在使用Visual Studio(2019或2022)与Git,并遇到了此问题,那么您可以从Git选项卡 ->设置中定义此选项。 重新拉取本地分支时进行变基 如果要使分支“合并”更改,则将其设置为false;如果要使更改“变基”,则将其设置为True。 请点击链接查看图片:VS 2019 - Git

3
这对我在 Visual Studio Enterprise 2022 上起了作用。 - jon.r

50

对我而言有效

git config --global pull.ff true

这对我有用,而其他解决方案(即使是最受欢迎的)给了我错误。谢谢。 - Rorrim
到目前为止,这是最好的答案。 - erwin
我收到了“致命错误:无法快进,正在中止”的消息。 - John Little
尝试使用 git pull --no-ff - Siddhartha Mukherjee

36

git config pull.ff only 或者等效的 git pull --ff-only 是最安全的命令。原因是,rebase(变基)可以覆盖掉历史记录,如果其他开发者强制推送到相同的分支,则可能导致提交的丢失。

但是这些命令都是有效的。


实际上,这种“提交丢失”的情况会如何发生? - user18099
不会发生“提交丢失”的情况。但是,如果有撤销和再次撤销,它可能会选择你不想要的更改的“内部”或“外部”。因此,它看起来好像丢失了撤消或再次撤消。此外,如果你习惯于注释旧代码,则更改可能应用于已注释的副本而不是你想要的副本。仅限于FF不进行任何修补,因此它很无聊但也很安全。 - user3710044
3
对我不起作用。致命错误:无法快进,正在中止。这是最简单的存储库,只有一个主分支和两个人。不幸的是,两个不是 git 专家的人同时编辑不同的文件对 git 来说是个问题。 - John Little

31

注意:早些时候,我们教授了 "git pull"(man) 的用法,以便在用户没有指定需要合并、变基或仅接受快进操作的历史记录时发出警告,但该警告会触发已设置 pull.ff 配置变量的用户。

但这种情况已不再存在(即:不再有警告),从 Git 2.29(2020年第4季度)开始实施。

参见提交 54200ce(2020年9月24日),由Alex Henrie (alexhenrie)进行了修改。
(由Junio C Hamano -- gitster --提交 299deea中合并,2020年9月29日)

pull:如果已设置pull.ff,则不发出警告

签署作者:Alex Henrie

一个理解如何设置 pull.ff 的用户不需要额外的说明。

在 Git 2.31(2021 年第一季度)之前,当用户没有告诉 "git pull"(man) 使用 rebase 或 merge 时,该命令会发出一个大声的消息,告诉用户选择 rebase 或 merge,但仍然创建了一个合并,强制那些想要 rebase 的用户重新执行操作。

通过加强条件来解决此问题的早期部分,以便在历史记录快进时不必停止或强制用户选择 rebase 或 merge。

查看 提交 7539fdc提交 b044db9(2020年12月14日)由Junio C Hamano (gitster).
查看 提交 c525de3提交 278f4be提交 77a7ec6(2020年12月12日)由Felipe Contreras (felipec).
(合并自Junio C Hamano -- gitster --提交 d3fa84d,2021年01月06日)

拉取:仅在非快进时显示默认警告

建议者:Junio C Hamano
签署者:Felipe Contreras

没有必要在每次拉取时显示烦人的警告... 只有那些不是快进的警告。

当前的警告测试仍然通过,但这并不是因为参数或配置,而是因为它们都是快进操作。

我们现在需要测试非快进的情况。


警告随着2.34(2021年第4季度)的更新发生了变化: "git pull"(man) 存在各种边缘情况,其 --rebase 后端未经周密考虑 ,例如 "git pull --ff-only"(man) 没有停止而是继续进行了 rebase,当另一侧的历史记录不是我们历史记录的一个后代时。

另请参阅: Git 2.34 尚未解决所有问题。

请查看提交 6f843a3提交 359ff69提交 031e2f7提交 adc27d6提交 e4dc25e(2021年7月22日),以及提交 1d25e5b提交 be19c5c(2021年7月21日)由Elijah Newren (newren)提交。
请查看提交 3d5fc24(2021年7月21日)由Alex Henrie (alexhenrie)提交。
(由Junio C Hamano -- gitster --合并于提交 7d0daf3,2021年8月30日)

pull:默认情况下在无法快进时中止

初始补丁由:Alex Henrie
签署者:Elijah Newren

我们已经有一段时间没有指定如何通过 git pull 协调不同分支时向用户显示了一个长的警告。
现在将其变为错误。

git pull 现在包含在其手册页面中:

将远程仓库的更改合并到当前分支中。
  • 如果当前分支落后于远程,则默认情况下它会将当前分支快进以匹配远程。
  • 如果当前分支和远程分支发生了分歧,则用户需要使用--no-ff--ff--rebase(或相应的配置选项pull.ffpull.rebase)来指定如何协调分歧的分支。

更准确地说,git pull使用给定的参数运行git fetch,然后根据配置选项或命令行标志,将调用git mergegit rebase来协调分歧的分支。

Pulling without specifying how to reconcile divergent branches is discouraged.
You can squelch this message by running one of the following commands sometime before your next pull:

git config pull.rebase false  # merge (the default strategy)
git config pull.rebase true   # rebase

你会看到:

You have divergent branches and need to specify how to reconcile them.
You can do so by running one of the following commands sometime before your next pull:

git config pull.rebase false  # merge (the default strategy)
git config pull.rebase true   # rebase
意思是,如果你不运行这些命令之一,你将会得到一个致命错误:
fatal: Need to specify how to reconcile divergent branches.

Git 2.35更新(2022年第一季度)

Ark Kun 报告:

Git 2.34仍然存在问题。它拒绝拉取一个当前分支头的祖先远程分支。
git失败而不是什么都不做。
VSCode有同步功能,可以进行拉取和推送。
由于GIT更改了行为,该功能已经破损了几个月。

幸运的是,这个问题在GIT主分支中终于得到了解决。

这个问题在Git邮件线程中被报告/讨论,并且正在进行修复(git commit ea1954a

在 Git 2.35(2022年第一季度)之前,无论使用哪种策略,当对方落后于我们时, "git pull"(man) 应该会成功执行,因为它是一个无操作,但实际上并没有。

请查看提交 ea1954a(2021年11月17日)由Erwin Villejo (erwinv)提交。
(由Junio C Hamano -- gitster --合并于提交 0f2140f,2021年11月21日)

pull:当已经是最新版本时应该是无操作的

签署者:Erwin Villejo

已经更新的拉取错误已经针对--ff-only进行了修复,但是它没有包括未指定--ff--ff-only的情况。 此次更新将--ff-only修复程序扩展到命令行标志或配置中未指定--ff--ff-only的情况。

在 Git 2.41 (Q2 2023) 中,当 "git pull"(man) 配置为 pull.rebase=false merge.ff=only 后,由于我们自己的开发,导致失败,给出建议信息以摆脱 "Not possible to fast-forward" 状态。

请查看提交 765071a(2023年3月7日)由Felipe Contreras (felipec)提交。
(由Junio C Hamano -- gitster --合并于提交 9de14c7,2023年3月19日)

建议:为新手添加不同的建议

签名者:Felipe Contreras
认可者:Taylor Blau

用户可能并不知道为什么只配置了 ff,也许是管理员这样做的,或者安装程序(Git for Windows)这样做的,或者他们只是遵循一些在线建议。
这不仅会发生在 pull.ff=only 上,还会发生在 merge.ff=only 上。
如果用户配置了 pull.rebase=falsemerge.ff=only,情况会更糟,因为在这些情况下,分叉合并将不断失败。
除了 git merge --no-ff(man),没有简单的方法可以解决这个问题。
让我们不要假设我们的用户是 Git 专家,完全理解他们所有的配置。

git config现在在其手册页面中包含以下内容:

diverging

当无法进行快进时显示的建议。

因此,您不仅可以看到:

Not possible to fast-forward, aborting.

你会看到:

Diverging branches can't be fast-forwarded, you need to either:

  git merge --no-ff

or:

  git rebase

Not possible to fast-forward, aborting.

1
在我的情况下,我在将git config设置为仅ff后,无法使用git pull进行ff。现在我该怎么办?git版本-2.33.1。 - y_159
1
Git 2.34仍然存在问题。它拒绝拉取一个远程分支,该分支是当前分支头的祖先。 - Ark-kun
@Ark-kun 但是如果远程分支是你当前本地分支的祖先(也就是包含在其中),那么就没有需要拉取的内容了,对吧? - VonC
会没有东西可以拉取,对吧?- 是的。但是Git会失败而不是什么都不做。VSCode有同步功能,可以进行拉取和推送。由于GIT更改了行为,该功能已经破损了几个月。幸运的是,这个问题终于在GIT主分支中得到了解决。等待发布... - Ark-kun
@Ark-kun 很有趣。你有关于那个修复的问题或拉取请求参考吗? - VonC
显示剩余3条评论

30

以上已经提到了几个很好的答案,但如果您觉得困惑,可以尝试这个方法(警告:如果您有本地更改,以下命令将清除更改):

以上内容翻译为:

已经有一些不错的答案被提及了,但如果您觉得困惑,可以尝试这个方法(警告:如果您在本地进行了修改,则以下命令将删除这些更改):

git reset --hard origin/<remote_branch_name>

例如:如果您的分支名称是master


git reset --hard origin/master

这个命令会放弃掉你本地分支的所有更改,并使你的本地分支与远程分支完全相同。换句话说,它使你的本地分支成为远程分支的一份副本。


1
谢谢 @pr17om,它对我有用。所有上面的答案在某种程度上都没有用。 - Priti
3
除非你知道自己在做什么,否则不要这样做。否则你可能会丢失本地工作! - Martino
@Martino,你是对的,但是这在帖子中已经明确提到了,它会丢弃任何本地更改并制作一个新的远程副本... - Pritom
我执行了 git reset --hard origin/dev 命令,但是出现了错误:无法确定参数 'origin/dev',可能是未知的版本或路径不在工作树中。 请使用 '--' 来分隔路径和版本,像这样: 'git <command> [<revision>...] -- [<file>...]'。 - Vitaly Zdanevich

24

尝试这个答案 -

您可以使用“git config pull.rebase false”命令切换回默认合并策略,而不是使用rebase。

git config pull.rebase false

然后使用您的拉取命令

git pull origin <Your branch name>

来自...

https://www.cyberithub.com/solved-fatal-need-to-specify-how-to-reconcile-divergent-branches/#:~:text=Solution%201%3A%20Switch%20to%20Merge%20Strategy&text=You%20can%20use%20git%20config,instead%20of%20using%20rebasing%20strategy.&text=After%20switching%20back%20to%20default,the%20changes%20from%20main%20branch


1
非常感谢,这件事困扰了我很久。 - undefined

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