浅克隆对 Travis 和其他 CI 服务的缺点?

Disadvantages of shallow cloning on Travis and other CI services?

大多数 CI 服务提供浅克隆存储库的方法。例如,在 Travis 上:

git:
  depth: 1

或在 AppVeyor 上:

clone_depth: 1
or
shallow_clone: true

这有明显的速度优势,因为您不必克隆整个存储库。

CI 服务的浅克隆有什么缺点吗?是否存在浅克隆会使 CI 构建失败的情况?否则,为什么浅克隆不是这些 CI 服务的默认设置?

通常不会发生的原因有两个。

首先,浅克隆的散列将不同于您在存储库中可能拥有的任何版本。因此,将无法跟踪您对任何特定结果所做的构建。

其次,如果您没有详细信息,大多数 Git 服务器都可以发送优化的 'everything.pack'。否则,服务器将不得不提供一个自定义提交包,其中仅包含要发送给您的浅表副本。因此,虽然可能有更多的数据通过线路传输,但实际上可能会导致服务器上的工作量增加。

最后,相当多的 CI 构建将执行某种标记操作并将其上传到存储库,实际上您不能标记浅克隆(见第 1 点)。

添加到 AlBlue 的回答:

另一个问题是克隆深度设置也用于 git 子模块。

在使用git子模块的项目中,Travis等会clone从master开始的子模块repo,然后查看具体的revision。

如果我们在子模块中指向的提交不在当前主模块的 n 个提交中(其中 n 是深度设置),那么它将无法检出。

默认行为和选项

Travis CI 上,默认行为是使用 50 的克隆深度。
TravisCI documentation, git-clone-depth:

git:
  depth: 3
# Or remove the --depth flag entirely with:
git:
  depth: false

AppVeyor 上,默认是克隆整个存储库。
AppVeyor 提供设置克隆深度和替代 shallow_clone: true 选项,其中使用 GitHub 或 Bitbucket API 将提交下载为 zip 存档。 (AppVeyor documentation.)

reference appveyor.yml中的描述:

# fetch repository as zip archive
shallow_clone: true                 # default is "false"

# set clone depth
clone_depth: 5                      # clone entire repository history if not defined

不要在 CI 的项目中使用 depth=1!

如果在 CI 平台开始克隆预期提交之前将新提交推送到分支,则使用 (clone_)depth: 1 通常会导致 git 错误。 在 AppVeyor 和 TravisCI 上,对 GitHub.

上的存储库进行正常的推送操作

AppVeyor 结帐失败的示例输出:

Build started
git clone -q --depth=1 --branch=<branch_name> https://github.com/<user>/<repo_name>.git C:\projects\<repo_name>
git checkout -qf 53f3f9d4d29985cc6e56764c07928a25d94477ed
fatal: reference is not a tree: 53f3f9d4d29985cc6e56764c07928a25d94477ed
Command exited with code 128

请注意,没有提取特定的提交!

使用 AppVeyors 替代方案 shallow_clone: true:

Build started
Fetching repository commit (6ad0f01)...OK
Total: 781.1 KB in 76 files

我没有发现使用 shallow_clone: true 设置的项目有任何问题。

重新启动旧提交的构建

使用有限深度时的次要结果是,如果超出此范围,重新启动 CI 旧提交的构建将失败。

建议

在 AppVeyor 上,如果存储库在 GitHub 或 Bitbucket 上可用,我建议使用 shallow_clone: true。 除非您想对代码进行 git 操作,否则这似乎是最佳选择。

在 TravisCI 上不设置深度(并使用默认深度 50)似乎是合理的。 如果您不想触发历史构建或根据存储库上的流量进行优化,您可以使用不同的值。

克隆依赖项

外部依赖通常通过分支或标签来引用。 当获取分支的提示或标签被克隆时,使用 git 标志 --depth=1.

应该没有问题

添加答案有点晚,但由于问题引用了“其他 CI 服务”,我确实想添加一个重要的位。

SonarQube 提供了一些非常详细的 CI 功能,这些功能引用了浅层克隆中不存在的 git blame 信息。来自 this link:

A full clone is required for this integration to be able to collect the required blame information (see Known Issues). If a shallow clone is detected, a warning will be logged and no attempt will be made to retrieve blame information.

如果您的 CI 系统主要只是“在最新版本上执行测试”,则这无关紧要。根据您的 CI 需求,额外几秒钟的构建以实现更好的分析可能是值得的。