# Optimizing GitLab for large repositories > 原文:[https://docs.gitlab.com/ee/ci/large_repositories/](https://docs.gitlab.com/ee/ci/large_repositories/) * [Shallow cloning](#shallow-cloning) * [Git strategy](#git-strategy) * [Git clone path](#git-clone-path) * [Git clean flags](#git-clean-flags) * [Git fetch extra flags](#git-fetch-extra-flags) * [Fork-based workflow](#fork-based-workflow) * [`shell` executor example](#shell-executor-example) * [`docker` executor example](#docker-executor-example) * [Our `.gitlab-ci.yml`](#our-gitlab-ciyml) * [Store custom clone options in `config.toml`](#store-custom-clone-options-in-configtoml) # Optimizing GitLab for large repositories[](#optimizing-gitlab-for-large-repositories "Permalink") 通常,由于克隆和签出所需的时间,在工作树中包含超过 5 万个文件的大型存储库通常需要特别考虑. GitLab 和 GitLab Runner 可以很好地处理这种情况,但是需要优化的配置才能有效地执行其操作. 处理大型存储库的一般准则很简单. 以下各节将更详细地描述每个准则: * 始终以增量方式获取. 请勿以导致重新创建所有工作树的方式进行克隆. * 始终使用浅克隆来减少数据传输. 请注意,由于 CPU 影响更大,这给 GitLab 实例带来了更多负担. * 如果您大量使用基于 fork 的工作流,请控制克隆目录. * 优化`git clean`标志,以确保删除或保留可能影响或加快构建速度的数据. ## Shallow cloning[](#shallow-cloning "Permalink") 在 GitLab Runner 8.9 中引入. 默认情况下,GitLab 和 GitLab Runner 始终执行完整克隆. 虽然这意味着已收到来自 GitLab 的所有更改,但通常会导致接收额外的提交日志. 理想情况下,您应始终使用`GIT_DEPTH` ,该数字应较小,例如 10.这将指示 GitLab Runner 执行浅表克隆. 浅克隆使 Git 仅请求给定分支的最新一组更改,最多达到`GIT_DEPTH`变量定义的所需提交`GIT_DEPTH` . 这极大地加快了从 Git 存储库获取更改的速度,特别是如果存储库积压的事务由很多个大文件组成的积压很长时,因为我们有效地减少了数据传输量. 以下示例使 GitLab Runner 浅表克隆仅获取给定的分支; 它不会获取任何其他分支或标签. ``` variables: GIT_DEPTH: 10 test: script: - ls -al ``` ## Git strategy[](#git-strategy "Permalink") 在 GitLab Runner 8.9 中引入. 默认情况下,GitLab 配置为始终首选`GIT_STRATEGY: fetch`策略. 如果在磁盘上找到`GIT_STRATEGY: fetch`策略,则会重新使用现有的工作树. 这与`GIT_STRATEGY: clone`策略不同, `GIT_STRATEGY: clone`一样,如果找到了工作树,则会在克隆之前将其删除. 首选使用`fetch` ,因为它会减少要传输的数据量,并且不会真正影响您可能会从 CI 对存储库执行的操作. 但是, `fetch`确实需要访问以前的工作树. 使用时,这种运作良好, `shell`或`docker`执行,因为这些努力保持 worktrees,默认情况下尽量重复使用它们. 目前不适用于`kubernetes`执行器,并且在使用`kubernetes` `docker+machine`时有限制. `kubernetes`执行器总是克隆到临时目录中. GitLab 还提供了`GIT_STRATEGY: none`策略. 这会禁用任何由 GitLab 完成的`fetch`和`checkout`命令,要求您执行这些操作. ## Git clone path[](#git-clone-path "Permalink") 在 GitLab Runner 11.10 中引入. [`GIT_CLONE_PATH`](../yaml/README.html#custom-build-directories)允许您控制在何处克隆源. 如果您在 fork 工作流中大量使用大型存储库,则可能会产生影响. 从 GitLab Runner 的角度来看,前叉工作流存储为具有单独工作树的单独存储库. 这意味着 GitLab Runner 无法优化工作树的使用,您可能必须指示 GitLab Runner 使用它. 在这种情况下,理想情况下,您希望使 GitLab Runner 执行程序仅用于给定项目,而不是在不同项目之间共享,以使此过程更高效. [`GIT_CLONE_PATH`](../yaml/README.html#custom-build-directories)必须在`$CI_BUILDS_DIR` . 当前,不可能从磁盘选择任何路径. ## Git clean flags[](#git-clean-flags "Permalink") 在 GitLab Runner 11.10 中引入. [`GIT_CLEAN_FLAGS`](../yaml/README.html#git-clean-flags)允许您控制是否要求对每个 CI 作业执行`git clean`命令. 默认情况下,GitLab 确保您的工作树在给定的 SHA 上,并且您的存储库是干净的. 设置为`none`时,将禁用[`GIT_CLEAN_FLAGS`](../yaml/README.html#git-clean-flags) . 在非常大的存储库上,这可能是理想的,因为`git clean`是磁盘 I / O 密集型的. 使用`GIT_CLEAN_FLAGS: -ffdx -e .build/`控制`GIT_CLEAN_FLAGS: -ffdx -e .build/` (例如)使您可以控制和禁用后续运行之间工作树中某些目录的删除,这可以加快增量生成的速度. 如果您重复使用现有计算机并拥有可用于构建的现有工作树,则效果最大. 有关[`GIT_CLEAN_FLAGS`](../yaml/README.html#git-clean-flags)接受的确切参数,请参见[`git clean`](https://git-scm.com/docs/git-clean)的文档. 可用参数取决于 Git 版本. ## Git fetch extra flags[](#git-fetch-extra-flags "Permalink") 在 GitLab Runner 13.1 中[引入](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) . [`GIT_FETCH_EXTRA_FLAGS`](../yaml/README.html#git-fetch-extra-flags) allows you to modify `git fetch` behavior by passing extra flags. 有关更多信息,请参见[`GIT_FETCH_EXTRA_FLAGS`文档](../yaml/README.html#git-fetch-extra-flags) . ## Fork-based workflow[](#fork-based-workflow "Permalink") 在 GitLab Runner 11.10 中引入. 遵循以上准则,让我们假设我们想要: * 针对大型项目进行优化(目录中有超过 5 万个文件). * 使用基于分叉的工作流进行贡献. * 重用现有的工作树. 预先配置了存储库的预配置运行器. * 赛跑者仅分配给项目和所有分叉. 让我们考虑以下两个示例,一个使用`shell` executor,另一个使用`docker` executor. ### `shell` executor example[](#shell-executor-example "Permalink") 假设您具有以下[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) . ``` concurrent = 4 [[runners]] url = "GITLAB_URL" token = "TOKEN" executor = "shell" builds_dir = "/builds" cache_dir = "/cache" [runners.custom_build_dir] enabled = true ``` This `config.toml`: * 使用`shell`执行器, * 指定一个自定义`/builds`目录,其中将存储所有克隆. * 启用指定`GIT_CLONE_PATH` , * 一次最多运行 4 个作业. ### `docker` executor example[](#docker-executor-example "Permalink") 假设您具有以下[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) . ``` concurrent = 4 [[runners]] url = "GITLAB_URL" token = "TOKEN" executor = "docker" builds_dir = "/builds" cache_dir = "/cache" [runners.docker] volumes = ["/builds:/builds", "/cache:/cache"] ``` This `config.toml`: * 使用`docker` executor, * 在磁盘上指定将存储所有克隆的自定义`/builds`目录. 我们在主机上挂载`/builds`目录,以使其在后续运行之间可重复使用,并允许其覆盖克隆策略. * 默认情况下已启用,因此未启用指定`GIT_CLONE_PATH`功能. * 一次最多运行 4 个作业. ### Our `.gitlab-ci.yml`[](#our-gitlab-ciyml "Permalink") 一旦配置了执行程序,就需要微调`.gitlab-ci.yml` . Our pipeline will be most performant if we use the following `.gitlab-ci.yml`: ``` variables: GIT_DEPTH: 10 GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_NAME build: script: ls -al ``` 上面配置了: * 浅克隆 10,以加快后续`git fetch`命令的速度. * 自定义克隆路径,使我们可以在父项目和所有分支之间重用工作树,因为我们对所有分支使用相同的克隆路径. 为什么要使用`$CI_CONCURRENT_ID` ? 主要原因是要确保使用的工作树在项目之间不冲突. `$CI_CONCURRENT_ID`表示给定执行器中的唯一标识符,因此只要我们使用它来构造路径,就可以确保该目录不会与其他正在运行的并发作业冲突. ### Store custom clone options in `config.toml`[](#store-custom-clone-options-in-configtoml "Permalink") 理想情况下,所有与作业相关的配置都应存储在`.gitlab-ci.yml` . 但是,有时希望使这些方案成为 Runner 配置的一部分. 在以上 Forks 的示例中,使此配置对于用户可发现可能是首选,但这会带来管理开销,因为需要为每个分支更新`.gitlab-ci.yml` . 在这种情况下,可能希望保持`.gitlab-ci.yml`克隆路径不可知,但是将其配置为 Runner. 我们可以使用以下规范扩展[`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) ,如果`.gitlab-ci.yml`不覆盖它,它将由 Runner 使用: ``` concurrent = 4 [[runners]] url = "GITLAB_URL" token = "TOKEN" executor = "docker" builds_dir = "/builds" cache_dir = "/cache" environment = [ "GIT_DEPTH=10", "GIT_CLONE_PATH=$CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_NAME" ] [runners.docker] volumes = ["/builds:/builds", "/cache:/cache"] ``` 这使得克隆配置成为给定 Runner 的一部分,并且不需要我们更新每个`.gitlab-ci.yml` .