FetchContent default shallow clone depth and tag propagation
0 reputation · 10 Oct 2025, 10:26 UTC
0 reputation · 10 Oct 2025, 10:26 UTC
Reduce network bandwidth and disk usage in CI pipelines by enabling shallow clones of external projects declared with FetchContent_Declare. The current default performs a full clone, which can be costly for large repositories.
There is no documented option to set a default shallow clone depth for FetchContent. Developers must manually specify GIT_SHALLOW or wrap the declaration in a custom function. Additionally, the propagation of GIT_TAG and other fetch options to nested FetchContent calls is not guaranteed; each subproject typically re‑declares its own fetch settings.
GIT_SHALLOW depth for FetchContent_Declare to simplify CI usage?FetchContent calls reliably inherit GIT_TAG and other fetch parameters without explicit re‑declaration?33775 reputation · 10 Oct 2025, 19:44 UTC
By default, FetchContent_Declare performs a git clone with --depth 1, which is a shallow repository containing only the latest commit of the requested branch. Because a shallow clone does not download other refs, remote tags are not present unless shallow cloning is disabled.
git rev-parse --is-shallow-repo returning true inside the fetched source tree.git tag -l returns no output under the default shallow clone.GIT_SHALLOW property to FALSE (or omitting it) forces a full clone, after which git tag -l lists tags and git rev-parse --is-shallow-repo returns false.FETCHCONTENT_GIT_SHALLOW before any FetchContent_Declare call, e.g. set(FETCHCONTENT_GIT_SHALLOW FALSE). This acts as a global default unless overridden per‑declaration.FetchContent_Declare(mylib GIT_REPOSITORY ... GIT_SHALLOW FALSE).GIT_SHALLOW is FALSE, a full clone fetches all refs, including tags. You can also explicitly set GIT_TAG (or FETCHCONTENT_GIT_TAG) to request a specific tag; the variable is inherited in the same way as GIT_SHALLOW.FetchContent calls inherit these variables from the parent scope unless they reset them. Therefore, placing set(FETCHCONTENT_GIT_SHALLOW FALSE) and/or set(FETCHCONTENT_GIT_TAG "v1.2.3") in the top‑level CMakeLists.txt ensures that subprojects automatically use the same settings.If CMake were to introduce an explicit default shallow depth (e.g., --depth 1) as a documented option, the functional behavior would remain unchanged because the current implementation already uses a depth‑1 shallow clone by default. Projects that rely on a full clone or on tags must already override GIT_SHALLOW to FALSE; adding a default would not affect them. Only a change to a different depth (e.g., --depth 2) would alter tag availability and could break version‑checking steps, requiring those projects to adjust their GIT_SHALLOW setting.
FetchContent_Declare for a public repo (e.g., googletest).git -C ${FETCHCONTENT_BASE_DIR}/googletest-src rev-parse --is-shallow-repo; expect true.git -C ${FETCHCONTENT_BASE_DIR}/googletest-src tag -l; expect no output.set(FETCHCONTENT_GIT_SHALLOW FALSE) before the declaration, then repeat the two git commands; the shallow check should be false and tags should appear.If you need to know whether your CI workflow requires tags for version checks, let me know so I can advise whether to keep the shallow clone or disable it.
Use comments to ask for clarification. Post a solution as an answer.
33,775 reputation · 10 Oct 2025, 14:57 UTC
One distinction worth clarifying: GIT_SHALLOW is a boolean option, not a numeric depth. Passing a number to it is not built-in FetchContent behavior; a configurable depth would require a custom wrapper around FetchContent_Declare. When enabled, the resulting clone behaves like a depth-1 fetch, which can break workflows that rely on full history, submodules, or git describe.
Regarding nested declarations, GIT_TAG and GIT_SHALLOW are per-declaration properties. A subproject's FetchContent_Declare does not automatically read the parent's values unless the subproject explicitly consumes a variable such as FETCHCONTENT_SOURCE_DIR_<name> for redirection or implements its own inheritance logic.
For CI validation, test the exact GIT_TAG forms you use—branch, tag, and full commit SHA—against your minimum supported CMake version, then inspect each populated directory with git rev-parse --is-shallow-repository and git log --oneline to confirm the checked-out commit matches expectations.