How to Checkout Submodules with actions/checkout: Configuration Guide and Examples
Set the submodules input to true for top-level submodules or recursive for nested submodules when using the actions/checkout GitHub Action to automatically fetch Git submodules during your workflow.
The actions/checkout repository provides a robust solution for cloning repositories in GitHub Actions workflows, including comprehensive support for Git submodules. When you need to checkout submodules with actions/checkout, the action handles the complex Git command orchestration internally while exposing a simple configuration interface. This implementation ensures that both public and private submodules are fetched using the appropriate authentication credentials.
How the Submodules Input Is Parsed and Executed
According to the source code in src/input-helper.ts, the action parses the submodules input to determine the checkout behavior. When you set submodules: true, the flag result.submodules becomes true; when you set submodules: recursive, the additional flag result.nestedSubmodules is also set to true.
During the checkout process, src/git-source-provider.ts orchestrates the submodule synchronization. The action executes git submodule sync to ensure submodule URLs match the parent repository's authentication settings. It then runs git submodule update --init --force to clone the submodules and checkout the correct commits.
If nestedSubmodules is enabled, the action passes the --recursive flag to fetch sub-submodules. The low-level Git operations are implemented in src/git-command-manager.ts, which provides the submoduleSync, submoduleUpdate, and submoduleForeach helper methods.
Additionally, src/git-auth-helper.ts updates the Git credential helper for each submodule. This ensures that the same token or ssh-key used for the main repository is available when fetching private submodules.
Submodule Checkout Configuration Options
The submodules input accepts three distinct values that control submodule behavior:
true– Checkout top-level submodules only, ignoring any nested sub-submodules.recursive– Checkout all submodules recursively, including nested sub-submodules.- (empty or omitted) – Submodules are ignored; only the main repository is checked out.
Practical Code Examples for Submodule Checkout
Basic Submodule Checkout (Top-Level Only)
Use this configuration when your repository contains only top-level submodules and you do not need nested dependencies.
- uses: actions/checkout@v7
with:
submodules: true # fetch only top-level submodules
token: ${{ secrets.GITHUB_TOKEN }}
Recursive Checkout for Nested Submodules
When your project contains nested submodules, specify recursive to ensure all levels are fetched.
- uses: actions/checkout@v7
with:
submodules: recursive # fetch all submodules recursively
token: ${{ secrets.GITHUB_TOKEN }}
Shallow Fetch with Submodules
To minimize checkout time, combine submodules with a shallow fetch depth. Note that this retrieves only the latest commit for each submodule.
- uses: actions/checkout@v7
with:
submodules: true
fetch-depth: 1 # default – only the tip of each submodule
Full History for Submodules
When you need complete commit history for submodules, set fetch-depth: 0 to fetch all history for both the main repository and submodules.
- uses: actions/checkout@v7
with:
submodules: recursive
fetch-depth: 0 # fetch all history for the main repo and submodules
Sparse Checkout Including Submodule Paths
Submodule fetching works with sparse-checkout, but you must explicitly include the submodule directory paths in your pattern.
- uses: actions/checkout@v7
with:
sparse-checkout: |
src/
lib/submodule/ # ensure the submodule path is listed
submodules: true
Private Submodules with SSH Authentication
For private submodules, use an SSH key to ensure authentication propagates to submodule repositories.
- uses: actions/checkout@v7
with:
submodules: recursive
ssh-key: ${{ secrets.SUBMODULE_SSH_KEY }}
ssh-known-hosts: ${{ secrets.SSH_KNOWN_HOSTS }}
Authentication Behavior for Submodules
Submodules inherit the same authentication credentials as the main repository. The src/git-auth-helper.ts file handles credential propagation, ensuring that the token or ssh-key provided in the workflow step is used when fetching private submodules. You do not need to configure separate authentication for submodules unless they reside on different hosts requiring different credentials.
Summary
- Set
submodules: trueto checkout top-level submodules, orsubmodules: recursiveto include nested submodules. - The action executes
git submodule syncandgit submodule update --init --forceviasrc/git-source-provider.tsandsrc/git-command-manager.ts. - Authentication automatically propagates to submodules through
src/git-auth-helper.ts. - Combine
submoduleswithfetch-depthto control history depth, or withsparse-checkoutto limit the working tree. - Use
ssh-keyinstead oftokenwhen accessing private submodules via SSH.
Frequently Asked Questions
Why are my nested submodules not being checked out?
If nested submodules are missing, you likely set submodules: true instead of submodules: recursive. The true value only fetches top-level submodules. According to the implementation in src/input-helper.ts, you must explicitly set the input to recursive to enable the nestedSubmodules flag, which adds the --recursive flag to Git commands in src/git-source-provider.ts.
How do I authenticate private submodules in actions/checkout?
Private submodules automatically use the same authentication method as the main repository. If you use a token, it propagates to submodules via the credential helper configured in src/git-auth-helper.ts. For SSH-based authentication, provide the ssh-key and optionally ssh-known-hosts inputs, and the action will use this key for all submodule URLs.
Can I use sparse-checkout with submodules?
Yes, sparse-checkout is compatible with submodules, but you must include the submodule directory paths in your sparse-checkout pattern. The submodule contents are fetched regardless of sparse-checkout settings, but the working tree will only populate the paths you specify.
Does fetching submodules work with shallow clones?
Yes, the fetch-depth setting applies to submodules when submodules is enabled. By default, the action performs a shallow fetch (fetch-depth: 1) for both the main repository and submodules. Set fetch-depth: 0 to retrieve complete history for all repositories.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →