GitLab CI/CD Sparse-Checkout Monorepo Performance Prompt
Speed up GitLab CI clones in large monorepos with sparse-checkout, shallow depth, and partial clone — fetch only the paths a job needs without breaking builds.
- Target user
- Platform engineers optimizing clone time for large monorepos in GitLab CI
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT, Cursor
The prompt
You are a senior platform engineer who cuts CI clone time in large monorepos. You know GitLab Runner's git handling (`GIT_STRATEGY`, `GIT_DEPTH`, `GIT_SUBMODULE_STRATEGY`), git sparse-checkout cones, partial clone filters, and — critically — how to narrow a checkout WITHOUT starving a build of files it quietly depends on. I will provide: - Repo shape (size, number of top-level projects, submodules, LFS?) - The slow job(s) and what path(s) they actually build/test - Current `.gitlab-ci.yml` git-related config - Symptoms (clone dominates job time / huge checkout / history walk needed) - Runner type and whether build dirs are reused Your job: 1. **Measure the baseline**: identify how much of job time is clone vs. work (`CI_DEBUG_TRACE` / runner timing) so the optimization is justified. 2. **Map each job's true file dependencies**: the project it builds PLUS shared config, tooling, generated files, and any path it reads at runtime. This cone, not just the project dir, is what must be checked out. 3. **Apply the right narrowing per job**: - `GIT_DEPTH` per job — shallow where no history is needed, deeper where `git describe`/changed-file detection is used. - Sparse-checkout cone via `GIT_STRATEGY` + a `pre_clone_script`/manual sparse setup, or partial clone `--filter=blob:none` for blob-lazy fetch. - `GIT_SUBMODULE_STRATEGY` and `GIT_SUBMODULE_PATHS` to fetch only needed submodules. 4. **Guard history-dependent steps**: any job doing `git describe`, changelog, or `git diff` for path-scoped rules needs enough depth or an unshallow step. 5. **Handle changed-path detection**: if jobs use `rules:changes`, ensure the fetch depth supports the comparison base (MR pipelines need the target branch reachable). 6. **Keep it debuggable**: document each job's cone so an excluded-file failure is traceable; prefer fresh clones while tuning. 7. **Report the win**: expected clone-time reduction and the risk (what each job now assumes is present). Deliverables: - Per-job git config (`GIT_DEPTH`, sparse cone, submodule scope) - The sparse-checkout setup block (runner variables or `pre_clone_script`) - The list of files each narrowed job still depends on (the cone) - History-walk safeguards for the jobs that need them Mark DESTRUCTIVE or RISKY: cones that might exclude silently-read files, `GIT_DEPTH: 1` on jobs that walk history, and partial clone rollout without measurement. --- Repo shape: [size, projects, submodules, LFS?] Slow job(s) + build path: [DESCRIBE] Current git CI config (YAML): [PASTE] Symptoms: [clone-dominated / huge checkout / history needed] Runner + reused dirs?: [DESCRIBE]
Run this prompt with AI
Test it, get an AI-improved version, or compare models — live in the Prompt Workspace. No copy-paste.
Why this prompt works
In a big monorepo, most jobs spend more time cloning than building — but naive narrowing breaks builds that quietly read shared files. This prompt insists on mapping each job’s real dependency cone (project + shared config + tooling) before narrowing, and separately guards the jobs that walk history, so you get the clone-time win without the “file not found” mystery.
How to use it
- Measure clone-vs-work time to justify the change.
- Map each job’s real file cone, not just its project dir.
- Apply per-job depth, sparse cone, and submodule scope.
- Keep enough history for jobs that use
git describe/changed-path rules.
Useful commands
# Set up a sparse cone manually (in a job)
git sparse-checkout init --cone
git sparse-checkout set projects/api libs/shared tools/ci
# Partial clone — defer blob download until a file is touched
git clone --filter=blob:none --sparse "$CI_REPOSITORY_URL" repo
# Unshallow just enough for a history walk
git fetch --deepen=50
git describe --tags # needs tags reachable
# See what sparse-checkout currently includes
git sparse-checkout list
GitLab CI patterns
Per-job shallow depth + submodule scope
build-api:
variables:
GIT_DEPTH: "1" # this job needs no history
GIT_SUBMODULE_STRATEGY: none # api build uses no submodules
script:
- cd projects/api && make build
release:
variables:
GIT_DEPTH: "0" # full history for git describe/changelog
script:
- git describe --tags
- ./scripts/changelog.sh
Sparse cone via runner pre_clone_script (config.toml)
[[runners]]
pre_clone_script = """
git config --global core.sparseCheckout true
"""
build-web:
variables:
GIT_STRATEGY: clone # fresh clone while tuning cones
before_script:
- git sparse-checkout init --cone
- git sparse-checkout set projects/web libs/ui tools/ci # the real cone
script:
- cd projects/web && npm ci && npm run build
Changed-path detection needs the target branch reachable
lint-changed:
variables:
GIT_DEPTH: "50" # enough to reach the MR target base
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
changes:
- "projects/web/**/*"
script:
- git fetch origin "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
- git diff --name-only "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"...HEAD
Common findings this catches
- A sparse cone that omits a shared config/generated file the build reads, causing distant “file not found” errors.
GIT_DEPTH: 1breakinggit describe, changelog, orrules:changesbase comparison.- Every job full-cloning a multi-GB monorepo when it builds one project.
- Submodules fetched wholesale when a job needs none.
- Partial clone rolled out fleet-wide without measuring the lazy-fetch cost.
When to escalate
- Monorepo so large that even sparse clone is slow — consider scalar/partial-clone server settings or a repo-cache mirror with platform.
- Cross-project build dependencies that make cones fragile — may need a proper build graph (Bazel/Nx) rather than checkout tricks.
- Persistent history needs across many jobs — evaluate a shared warm cache volume on self-hosted runners.
Related prompts
-
GitLab CI Cache Policy Pull-Push Split Prompt
Split a single shared GitLab CI cache into a pull-only consumer pattern and a dedicated push job to stop concurrent jobs from clobbering each other's cache.
-
GitLab Monorepo CI/CD Prompt: Selective Builds & Child Pipelines
Design GitLab CI/CD for monorepos — selective builds via rules:changes, per-service child pipelines, shared-library detection and dependency-aware fan-out.
-
GitLab Pipeline Audit & Slow Job Hunt Prompt
Audit GitLab pipelines for stale jobs, queueing delays, runner capacity issues, and find the slow jobs that dominate critical path.
-
GitLab Parent/Child & Multi-Project Pipeline Design Prompt
Design parent/child pipelines, multi-project triggered pipelines, and downstream pipeline orchestration — `trigger:`, dynamic child generation, cross-project dependencies.
More GitLab CI/CD prompts & error guides
Browse every GitLab CI/CD prompt and troubleshooting guide in one place.
Reading prompts? Get all 500 in one free PDF
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.