What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

For a multi-repository project, keep each dependency at an explicit commit and make CI check out that exact commit, including any nested submodules. A Git submodule is not a copied folder: the superproject records a gitlink pointing to a commit in the submodule’s own repository. CI must also be configured to populate submodules and obtain credentials that can read every private dependency. With two CI systems, first decide which system owns each check and how both validate the same pinned set of commits.

What a gitlink records—and what it does not

A submodule is a separate Git repository checked out beneath a superproject. The superproject’s tree contains a gitlink entry naming the commit expected at the submodule path; it does not copy the dependency’s files or history into the superproject. The submodule retains its own repository history. Git’s submodule documentation describes the gitlink as the commit the superproject expects the submodule working directory to be at.

The .gitmodules file maps a submodule’s logical name to its working-tree path and default clone URL. A relative URL is resolved against the superproject’s origin. That can be convenient when related repositories move together, but GitLab warns it may resolve incorrectly in fork workflows; use an absolute URL if forks are expected. Git’s .gitmodules documentation explains the configuration, and GitLab Runner’s configuration documentation discusses the fork caveat.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How to change a dependency without losing reproducibility

By default, git submodule update checks out the commit recorded by the superproject. The submodule is commonly left on a detached HEAD, which is suitable for a build but not a place to make a commit you intend to maintain. Git’s submodule command documentation covers update behavior; the free online Pro Git submodules chapter walks through a practical workflow.

  1. In the submodule, switch to or create a working branch before editing.

  2. Commit and publish the change to the submodule’s own repository.

  3. Return to the superproject and stage the submodule path. Git records the new commit as a changed gitlink.

    Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  4. Commit and publish the superproject change so the dependency update is explicit and reviewable.

A build that follows a branch’s latest remote commit can change even when the superproject has not changed. GitLab documents the security, stability, and reproducibility risks of using --remote; its guidance says that, in most cases, projects should explicitly track submodule commits and update them deliberately, for example with a dependency bot. See GitLab Runner configuration.

What CI must do differently from a local checkout

A successful checkout of the superproject does not by itself guarantee that submodule working trees are populated. The CI checkout phase must initialize and update them at the recorded commits. If a submodule contains its own submodules, checkout must also recurse into those nested dependencies. Separately, the job needs credentials authorized to read each private repository; a checkout option cannot grant repository access that the token does not have.

GitLab CI/CD: configure depth, recursion, and access

GitLab Runner uses GIT_SUBMODULE_STRATEGY to control checkout: normal initializes top-level submodules, while recursive also handles nested submodules. The runner documentation also describes GIT_SUBMODULE_DEPTH, GIT_SUBMODULE_PATHS, and GIT_SUBMODULE_UPDATE_FLAGS; for example, update flags can pass --jobs to fetch in parallel. Submodule depth is separate from the main repository’s GIT_DEPTH. Consult the current GitLab Runner configuration documentation for syntax and version-specific behavior.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a private submodule fetched with CI_JOB_TOKEN, the submodule project must allow job-token access, and the user whose permissions apply to the job must have an appropriate role. A GitLab job token from one GitLab instance cannot authenticate to a different instance; for that case, use a credential for the external instance that has repository read access, and store it as a protected, masked CI variable. Follow current Runner guidance for credentials used by later Git commands inside submodule directories: externalized credentials may not automatically carry over. Verify behavior in the actual runner environment, especially when using a shell executor. The relevant details are in GitLab Runner’s configuration documentation.

GitHub Actions: checkout option and token scope

The official actions/checkout documentation supports submodule checkout with submodules: true or submodules: recursive. The recursive setting is the appropriate choice when nested submodules must be populated. The documentation also states that github.token is scoped to the current repository. A private or internal secondary repository therefore needs the documented separate credential option and a token with suitable access. Check the exact action version, workflow token permissions, and repository policy in use; enabling submodule checkout does not itself authorize access to another private repository.

How to divide work between two CI systems

“Dual CI” does not specify whether both systems build every repository, one validates while another deploys, or each repository owns its own pipeline. There is no single configuration implied by having two systems. Write down the project’s operating model before configuring triggers or credentials:

For reproducible integration, treat the superproject commit as the record of a tested dependency combination. Each CI system that validates that combination should check out the same superproject revision and populate its submodules from the recorded gitlinks. If one pipeline validates a new dependency commit, update the gitlink in the superproject before treating that combination as the project’s tested state.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common failure points to check

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.