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 in git tag -l. You can successfully run git 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: 0 creates a full clone, the fetch-tags input has no effect, as standard git clone behavior automatically includes all reachable tags.

Summary

  • The fetch-tags option only affects shallow clones where fetch-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) and src/git-command-manager.ts (command execution).
  • With fetch-depth: 0, the fetch-tags setting 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →