子模块和'git pull --rebase'

问题描述 投票:4回答:2

我们最近切换到git,并试图使用子模块来包含我们的Common库。

无论我们做什么,我们都无法在超级或子模块中使'git pull --rebase'工作。

我们得到:

james:libraries james$ git pull --rebase
Cannot pull with rebase: You have unstaged changes.
Please commit or stash them.

即使我们根本没有进行任何本地更改并拥有一个干净的目录,也会发生这种情况。对我们可能做错的事情有任何想法吗?

谢谢!詹姆斯

git macos git-submodules git-pull
2个回答
1
投票

在这里进行测试后,在子模块中进行更改不会阻止您对父级执行pull --rebase。因此,或者您正在子模块中执行pull --rebase,并且在那里没有隐匿的更改,或者您可能是使用git子模块add url添加了子模块,但是没有提交子模块添加,这将导致父级拒绝拉。您可以发布git status的输出吗?


0
投票

我们无法在超级或子模块中使用'git pull --rebase'来工作>>

[为了确保涉及子模块,请使用Git 2.14(2017年第三季度,OP提出问题的第六年)或更多带有“ git pull --rebase --recurse-submodules

”的知识,该知识可将子模块中的分支重新建立为更新后的基础。

请参阅commit e8906a9(2017年6月27日,以及commit a6d7eb2commit 8c69832commit 886dc15(2017年6月23日)。((由Stefan Beller (stefanbeller)stefanbeller中合并,2017年7月13日)>

[Junio C Hamano -- gitster --:可选地为子模块重新设置基础(仅更改远程子模块)]

签名人:布兰登·威廉姆斯

签名人:Stefan Beller

提供[--recurse-submodules]后,请教gitster可选地更新子模块。

[在特定情况下给定[commit c9c63ee”和“ pull”标志时,这将教pull运行“ pull”。

在基准工作流程上:
  1. 双方均更改子模块

让我们在子模块中假设以下历史记录:

pull

和超级项目中的以下内容(在括号中记录的子模块:]

submodule update --rebase

在理想情况下,这将使子模块变基并重写超级项目所指向的子模块指针,从而使超级项目看起来像

--recurse-submodules

和子模块为:

--rebase
H---I---J---K---L local branch
     \
      M---N---O---P remote branch

并且如果子模块中发生冲突,则超级项目的重新设置将在发生子模块冲突的提交时停止。

当前,超级项目中的“ A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch ”会产生合并冲突,因为子模块指针的更改有冲突,无法解决。


  1. 仅本地子模块更改

假设历史与上述相同,除了远程分支将不包含子模块更改,然后结果为

A(H)---B(I)              F(K')---G(L')  rebased branch
         \                /
         C(N)---D(N)---E(P) remote branch

是可取的。这是当前在rebase中发生的事情。

如果给出了递归标志,理想的git将产生一个超级项目,如下:

J---K---L (old dangeling tip)

和子模块为:

              J'---K'---L' rebased branch
             /
M---N---O---P remote branch
pull --rebase

此补丁程序无法解决此问题,但是添加了一个测试,该操作会在前面失败。


  1. 仅远程子模块更改

假设历史与(1)相同,只是本地超级项目分支不会接触子模块,因此在超级项目中,基础已经可以正常工作而没有冲突:

A(H)---B(I)               F(K)---G(L)  rebased branch
         \                /
         C(I)---D(I)---E(I) remote branch

此修补程序中显示的递归标志将另外将子模块更新为:

A(H)---B(I)              F(K')---G(L')  rebased branch (incl. sub rebase!)
         \                /
         C(I)---D(I)---E(I) remote branch

由于没有从超级项目中引用J,K,L或J',K',L',因此不需要重写超级项目的提交。


'J---K---L (old dangeling tip) 的结论

如果没有本地超级项目更改,则只需调用“ J'---K'---L' locally rebased branch / M---N---O---P advanced branch ”,这将产生所需的结果。在发生冲突的情况下,其行为与假定为健全的'A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch '中的行为相同。

此补丁仅实现(3)。


在合并工作流程上:

我们将使用与重新编制工作流中(1)中相同的基础DAG。因此,在理想情况下,“ H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch ”将产生以下结果:

pull --rebase --recursive

[submodule update --rebase作为子模块中的新合并提交,而超级项目为:]]

submodule update --recursive

但是pull --merge --recursive不支持动态修改子模块,因此H---I---J---K---L----X \ / M---N---O---P 不易在单个补丁中生成。实际上,X根本不了解子模块。

但是,当至少一侧完全不包含涉及子模块的提交时,我们就不需要为该子模块执行合并,而是可以通过签入A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) git merge子模块。

已经在git merge中实现了此策略(“为子模块实现自动快速转发合并”,2010-07-07,Git v1.7.3-rc0-Y(X)),因此为了与重新设置行为保持一致,我们还需要更新子模块的工作树。


在Git 2.27之前(2020年第二季度),“ git merge”尝试运行重新设置,即使在注意到拉动导致快速前进并且在没有错误的情况下也不需要重新设置,在过去的几年中,由于一个错误注意到。

请参阅git mergeL(2020年3月27日)。((由P合并于68d03e4a6e,2020年4月22日)>

merge:避免同时运行合并和变基

签名人:伊利亚·纽伦

git pull --rebase为真时,我们仍然首先检查是否可以快进。如果分支是可快速转发的,则我们可以避免重新设置基础,而只需使用merge即可执行快速转发逻辑。

但是,当commit fbae70d(“ Elijah Newren (newren):可选地重新设置子模块的基数(仅对远程子模块进行更改)”,2017-06-23,Git v2.14.0-rc0-newren添加了重新设置基数的功能子模块,这意外地导致我们同时运行合并和变基。

添加标志以避免两者同时发生。

当用户将Junio C Hamano -- gitster --gitster都设置为true时发现。

在这种情况下,运行合并和重新设置都会导致commit dfdce31更新两次(并且与HEAD匹配,而不是重新启动重新提交之前的提交),这超出了预期。

© www.soinside.com 2019 - 2024. All rights reserved.