How Cone Mode Sparse Checkout Works in actions/checkout

Cone mode sparse checkout in actions/checkout delegates directory pattern matching to Git's native sparse-checkout set command, automatically falling back to manual file manipulation only when the legacy non-cone mode is explicitly disabled.

Sparse checkout allows Git repositories to check out only a subset of files, dramatically reducing workspace size and clone times. The actions/checkout GitHub Action implements this feature using Git's modern cone-mode algorithm by default, which offers superior performance over legacy pattern matching. Understanding how this mechanism works within the action's TypeScript source code helps you optimize CI/CD pipelines for large monorepos.

Input Configuration and Parsing

The cone mode feature is controlled through the sparse-checkout-cone-mode input parameter declared in action.yml. By default, this boolean value is set to true, ensuring modern Git installations use the optimized cone algorithm.

In src/input-helper.ts, the action parses this input at lines 118-121:

result.sparseCheckoutConeMode =
  (core.getInput('sparse-checkout-cone-mode') || 'true').toUpperCase() ===
  'TRUE'

This parsing logic ensures that any input other than the explicit string "false" defaults to cone mode, maintaining backward compatibility while encouraging the modern code path.

Runtime Mode Selection

Once inputs are parsed, src/git-source-provider.ts determines which checkout strategy to execute. At lines 261-266, the provider checks the sparseCheckoutConeMode flag and branches accordingly:

if (settings.sparseCheckoutConeMode) {
    await git.sparseCheckout(settings.sparseCheckout)
} else {
    await git.sparseCheckoutNonConeMode(settings.sparseCheckout)
}

If cone mode is enabled, the code invokes git.sparseCheckout(), which interfaces directly with Git's native sparse-checkout implementation. When disabled, it calls git.sparseCheckoutNonConeMode(), triggering the legacy behavior.

Native Git Integration

The cone mode implementation resides in src/git-command-manager.ts. The sparseCheckout method receives an array of directory patterns and delegates entirely to Git's CLI:

async sparseCheckout(sparseCheckout: string[]): Promise<void> {
    await this.execGit(['sparse-checkout', 'set', ...sparseCheckout])
}

This command utilizes Git's built-in cone-mode handling, which constructs a directory cone containing only the specified paths and their contents. Because the heavy lifting occurs inside Git itself, this approach is significantly faster and more reliable than manual pattern file manipulation.

Legacy Fallback Mechanism

When users explicitly set sparse-checkout-cone-mode: false, the action falls back to the legacy non-cone implementation. The sparseCheckoutNonConeMode method in src/git-command-manager.ts manually enables sparse checkout and writes patterns to the Git metadata:

async sparseCheckoutNonConeMode(sparseCheckout: string[]): Promise<void> {
    await this.execGit(['config', 'core.sparseCheckout', 'true'])
    const output = await this.execGit(['rev-parse', '--git-path', 'info/sparse-checkout'])
    const sparseCheckoutPath = path.join(this.workingDirectory, output.stdout.trimRight())
    await fs.promises.appendFile(sparseCheckoutPath, `\n${sparseCheckout.join('\n')}\n`)
}

This method explicitly sets core.sparseCheckout to true, retrieves the path to .git/info/sparse-checkout, and appends the patterns directly to that file. While functionally equivalent for simple patterns, this method lacks the performance optimizations and recursive directory handling that cone mode provides.

Version Compatibility Checks

Before executing either path, the action verifies that the runner's Git version supports sparse checkout. The code checks against MinimumGitSparseCheckoutVersion in src/git-source-provider.ts (lines 53-57). If the installed Git version is older than the required minimum, the action disables sparse checkout entirely to prevent runtime errors.

Configuration Examples

Enabling Cone Mode (Default)

- uses: actions/checkout@v7
  with:
    sparse-checkout: |
      src/
      docs/
    sparse-checkout-cone-mode: true

Disabling Cone Mode (Legacy)

- uses: actions/checkout@v7
  with:
    sparse-checkout: |
      src/
      docs/
    sparse-checkout-cone-mode: false

Summary

  • Cone mode is the default sparse checkout behavior in actions/checkout, utilizing Git's native sparse-checkout set command for optimal performance.
  • The sparse-checkout-cone-mode input controls the algorithm selection, defaulting to true in src/input-helper.ts.
  • When enabled, src/git-source-provider.ts routes to sparseCheckout() in src/git-command-manager.ts, which executes git sparse-checkout set with the provided patterns.
  • When disabled, the action falls back to sparseCheckoutNonConeMode(), manually configuring core.sparseCheckout and writing to .git/info/sparse-checkout.
  • The action validates Git version compatibility against MinimumGitSparseCheckoutVersion before attempting any sparse checkout operations.

Frequently Asked Questions

What is the difference between cone mode and non-cone mode in sparse checkout?

Cone mode restricts sparse checkout patterns to directory-level cones (directories and their contents), which Git optimizes internally for performance. Non-cone mode uses the legacy pattern matching system that reads from .git/info/sparse-checkout and supports complex glob patterns but runs slower. The actions/checkout implementation reflects this distinction: cone mode calls git sparse-checkout set directly, while non-cone mode manually edits the sparse-checkout file.

How do I enable or disable cone mode in my workflow?

Set the sparse-checkout-cone-mode input to true or false in your workflow YAML. By default, actions/checkout enables cone mode automatically. To force legacy behavior, explicitly set sparse-checkout-cone-mode: false alongside your sparse-checkout patterns.

What Git version is required for cone mode sparse checkout?

The action checks for MinimumGitSparseCheckoutVersion in src/git-source-provider.ts before executing sparse checkout commands. While Git introduced the sparse-checkout command in version 2.25, the action validates the runner's Git version to ensure compatibility. If the version check fails, sparse checkout is disabled to prevent execution errors.

Why does cone mode perform better than the legacy implementation?

Cone mode delegates pattern matching and directory traversal to Git's native C implementation rather than interpreting patterns in TypeScript or relying on Git's slower legacy sparse checkout parser. According to the source code in src/git-command-manager.ts, the cone mode path executes a single git sparse-checkout set command, whereas non-cone mode requires multiple Git config calls and manual file system operations to append patterns to .git/info/sparse-checkout.

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 →