How Does the fetch-tags Option Work with Shallow Clones in actions/checkout
When you configure a shallow clone using fetch-depth greater than zero, setting fetch-tags: true instructs the action to execute an additional git fetch --tags --depth=<N> command that retrieves only the tag references pointing to commits within the fetched history, while the default false leaves tags un fetched.
The actions/checkout repository provides the official GitHub Action for checking out repository code within workflows. When working with shallow clones to improve performance, understanding how the fetch-tags option works with shallow clones is essential for controlling which Git tags are available in your CI environment. The implementation parses this configuration in src/input-helper.ts and executes the appropriate Git commands in src/git-command-manager.ts.
The Mechanics of Shallow Cloning and Tag Retrieval
Why Tags Are Excluded by Default
When you specify fetch-depth with a value greater than zero, the action performs a shallow git clone --depth <N> that retrieves only the most recent N commits of the default branch. By default, Git omits tags from shallow clones because tag references may point to commits that lie outside the limited history range, which would require fetching additional objects beyond the specified depth.
How fetch-tags Modifies Clone Behavior
Setting fetch-tags: true triggers a supplementary fetch operation after the initial shallow clone. According to the source code in src/git-command-manager.ts, the action conditionally appends a git fetch --tags --depth=<N> command (or git fetch --tags --no-tags --depth=<N> depending on the Git version) when both fetch-depth > 0 and fetch-tags === true. This retrieves all tag objects that reference commits within the shallow history, while tags pointing to older commits remain unavailable because their target commits are not present locally.
Source Code Implementation
The fetch-tags input is processed in src/input-helper.ts, where the boolean value is parsed from the workflow configuration. The actual Git command construction occurs in src/git-command-manager.ts, which determines whether to append the tag-fetching logic to the clone sequence based on the combined state of fetch-depth and fetch-tags.
Configuration Examples
Shallow Clone Without Tags (Default)
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 5 # only the last 5 commits
fetch-tags: false # (default) – no tags are fetched
Shallow Clone With Recent Tags
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 10 # retrieve the last 10 commits
fetch-tags: true # fetch tags that point to those 10 commits
Full Clone (fetch-tags Is Unnecessary)
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history
fetch-tags: true # ignored, tags are fetched automatically
Behavior with Partial Tag History
When using fetch-tags: true with a shallow clone, the action exhibits specific behaviors regarding tag availability:
-
Tags within depth: If a tag points to a commit within the specified
fetch-depth, the tag reference is fetched and appears ingit tag -l. You can successfully rungit rev-parse <tag>against these references. -
Tags outside depth: If a tag references a commit older than the shallow depth allows, the action cannot retrieve the tag because the underlying commit object is missing from the local repository. The action silently ignores these unreachable tags.
-
Full clones: When
fetch-depth: 0creates a full clone, thefetch-tagsinput has no effect, as standardgit clonebehavior automatically includes all reachable tags.
Summary
- The
fetch-tagsoption only affects shallow clones wherefetch-depth> 0. - When enabled, the action executes an additional
git fetch --tags --depth=<N>to retrieve tags pointing to commits within the shallow history. - Tags referencing commits outside the specified depth remain unavailable because the requisite commit objects are not present.
- The logic is implemented in
src/input-helper.ts(input parsing) andsrc/git-command-manager.ts(command execution). - With
fetch-depth: 0, thefetch-tagssetting is ignored since full clones automatically include all tags.
Frequently Asked Questions
What happens if a tag points to a commit outside the shallow depth?
The action cannot retrieve the tag because shallow clones exclude the underlying commit object. When fetch-tags: true is set, the action only fetches tags that reference commits within the available history; tags pointing to older commits are silently ignored and will not appear in git tag -l.
Does fetch-tags have any effect when fetch-depth is 0?
No. When fetch-depth: 0 configures a full clone, the fetch-tags input is ignored. Standard Git clone behavior automatically fetches all reachable tags, making the explicit option unnecessary in this scenario.
How is the git fetch --tags command constructed in the source code?
The src/git-command-manager.ts file constructs the command by conditionally adding git fetch --tags --depth=<N> (or with --no-tags depending on Git version) to the fetch sequence. This only occurs when the parsed inputs indicate both a shallow clone (fetch-depth > 0) and explicit tag fetching (fetch-tags === true).
Can I use fetch-tags with a specific fetch-depth value?
Yes. You can combine any positive integer value for fetch-depth with fetch-tags: true. The action will fetch exactly N commits deep and then retrieve any tags that point to those specific commits. This provides a balance between repository size and tag availability for recent history.
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 →