Jenkins构建中Git子模块未更新

93

我在Jenkins项目中有一个子模块。我已启用递归更新子模块的高级设置。

当我运行构建时,我发现工作区有来自子模块的文件。问题是,它似乎是子模块的第一个版本。当我推送更改(存储在GitHub上的仓库)时,Jenkins似乎没有更新子模块以获取正确的更改。是否有人见过这种情况?

9个回答

109
请注意Jenkins Git插件2.0将拥有“高级子模块行为”,这应该确保子模块的正确更新:

git 2.0

正如vikramvi评论的:

高级子模块行为 > 在该字段 "Path of the reference repo to use during submodule update" 中,添加子模块 git url。

Path


Owen B评论中提到

对于认证问题,现在有一个“使用父仓库的默认远程凭据”选项

JENKINS-20941中可以看到:

https://issues.jenkins-ci.org/secure/attachment/33245/Screen%20Shot%202016-07-08%20at%2010.09.17.png


6
但是如何操作呢?您能否提供详细的步骤和选择哪些选项?谢谢。 - zavié
8
我认为你应选择“高级子模块行为”,然后勾选出现的“递归更新子模块”复选框,并点击保存。 - KajMagnus
9
如果您正在使用私有存储库,这种方法可能行不通。 - Erik
1
使用私有仓库时,对我来说完美运行。 - davegallant
3
如果您的仓库不需要身份验证即可读取Git子模块,则此方法有效。这是Jenkins的一个错误。 - Ernst Kuschke
显示剩余12条评论

38
这在Jenkins网站上的Git插件文档中有详细说明,位于递归子模块部分。 摘录

GIT插件支持具有子模块的存储库,这些子模块本身又具有子模块。不过必须开启此功能:在作业配置 -> 源代码管理部分,Git -> 高级按钮(在要构建的分支下) -> 递归更新子模块

示例

从作业的配置屏幕中,在源代码管理部分,拉动添加按钮并选择“高级子模块行为”。

   s1

                                 s2

然后选择“递归更新子模块”:

   s3


1
谢谢,但是当我尝试过这个方法时(大约两年前),它并没有起作用。 - Ben
@Ben - 好的,我刚刚尝试了一下,这对我起作用了。可能与你的版本有关。 - slm
1
只有在您的存储库不需要身份验证才能读取您的git子模块时,此方法才有效。 - Ernst Kuschke
@ErnstKuschke - 我相信可以给Jenkins提供一个SSH密钥,以便它也可以与需要身份验证的存储库进行交互。 - slm

32

您是否知道,您的Git仓库始终引用子模块的特定修订版本?Jenkins不会自动更改修订版本。

如果您想使用更新的子模块修订版本,则必须在本地Git仓库中执行此操作:

cd submoduledir
git pull
cd ..
git add submoduledir
git commit -m 'Updated to latest revision of submoduledir'
git push # Go and watch Jenkins build with the new revision of the submodule

当你这样做时,Jenkins将在构建过程中检出子模块的完全相同版本。 Jenkins不会自行决定使用哪个子模块版本。 这是Git子模块和SVN externals之间的根本区别。
你可能想阅读有关子模块的良好参考资料,例如http://progit.org/book/ch6-6.html

1
@sti提供的ProGit链接已经过时。我认为这是当前等效的链接https://git-scm.com/book/en/v2/Git-Tools-Submodules。 - Stevel
链接已经失效(与HTTPS相关?)-“502 Bad Gateway”。 - Peter Mortensen

19

最终我找到了一个简单的方法来解决这个问题。

问题:

使用凭据进行的初始克隆正常工作,但随后的submodule克隆会因凭证不正确而失败。

  1. 自动高级子模块克隆:源代码管理 >>其他行为 >>高级子模块行为:导致凭证错误。
  2. Execute Shell部分中的git submodule update --init也会因凭证错误而失败。

解决方案:

我正在使用jenkins-1.574

  1. 勾选Build Environment >> SSH代理框。
  2. 选择正确的凭证(可能与源代码管理部分中选择的凭证相同)
  3. Execute Shell部分更新子模块

git submodule sync
git submodule update --init --recursive

这是一个屏幕截图enter image description here


3
没有这样的复选框了。 - adi518

13

看起来我找到了一个解决办法:

我添加了一个构建步骤来执行以下 shell 命令:

git submodule foreach git checkout master
git submodule foreach git pull

执行完这些命令后,你可能需要在超级项目中进行提交,因为子模块中的 HEAD 已经被更新了。 - slacy
嗨Ben,你能分享更详细的解决方案吗?我也想做同样的事情。另外,只是确认一下,你的解决方案会将项目的子模块git submodule更新到工作区,对吗? - Kim Stacks
没有比这更详细的信息了。我只是在我的构建过程中添加了这两行代码,它总是拉取子模块的最新版本。 - Ben
11
就像另一个回答中@sti所说,你似乎正在尝试使用Git子模块来代替SVN externals。不要将这些命令添加到Jenkins中,最好将正确的子模块版本提交到你的主Git存储库中。这样,Jenkins在构建项目特定版本时,始终会检出相同版本的子模块。可重现的构建是一件好事情。 - Cody Casterline
4
我发现了一个指令,你可能会觉得它更有用,特别是如果你没有在子模块中使用主分支,则可以尝试 git submodule update --init --recursive - Corey Scott

7

如果您正在使用Jenkins Git模块,可以将其设置为“在构建之前清除工作区”,这样它就始终可以获取正确的子模块。


6
我正在使用带有checkout插件的脚本化流水线。如果您想让子模块与您的存储库相同,只需像这样关闭trackingSubmodules选项:
checkout([$class: 'GitSCM', branches: [[name: '*/develop']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: false, reference: '', trackingSubmodules: false]], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '[myCredentials]', url: 'https://git.myRepo.git']]])

1
此答案不依赖于特殊的插件配置。 - akahunahi
最佳答案!应该通过现有的Jenkins API配置子模块。 - Nikita

2
在“高级子模块行为”中,勾选“将跟踪的子模块更新到分支的最新版本”。

Reference Image


你的回答可以通过添加更多支持信息来改进。请进行[编辑]以添加进一步的细节,例如引用或文档,以便他人可以确认您的答案是正确的。您可以在帮助中心中找到有关撰写良好答案的更多信息。 - Community
这对我有效。 - Bhavesh
这应该是被接受的答案,非常好用,只需一个简单的点击! - JBoy

0
我无法使 `scmGit` 与子模块一起正常工作。构建在调用本地 `git` 时失败,错误信息如下:
```shell /usr/bin/git config --get submodule..url" 返回状态码 1: ```
因此,我采用了丑陋的黑客解决方案,手动初始化子模块。
scmGit ...
sh 'git submodule add --force "<sub-path>" "<sub-name>"'

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