Actions/Checkout Performance: How to Optimize Repository Cloning in GitHub Actions

The actions/checkout action minimizes workflow runtime through shallow cloning and selective data transfer, but performance degrades significantly when fetching full history, large binary files, or falling back to the REST API.

The actions/checkout action serves as the entry point for nearly every GitHub Actions workflow, making its performance considerations critical for overall CI/CD pipeline efficiency. By default, the action is optimized for speed, but various inputs parsed in src/input-helper.ts and executed through src/git-source-provider.ts allow users to trade speed for completeness. Understanding these configuration options helps prevent unnecessary network transfer and disk I/O that can add seconds—or minutes—to your build times.

Shallow Cloning with fetch-depth

The default fetch-depth: 1 setting performs a shallow clone, retrieving only the single commit that triggered the workflow. As implemented in src/git-source-provider.ts (lines 174-202), this minimizes network traffic and disk I/O, which is why the default configuration is fastest for most CI/CD use cases.

If you set fetch-depth: 0, the action fetches the entire Git history for all branches and tags. This dramatically increases the amount of data transferred and can add seconds to the checkout step while consuming significantly more storage on the runner.

Partial Clones Using the filter Input

When you provide a filter input, the action performs a partial clone using --filter=blob:none by default. According to the source code in src/git-source-provider.ts (lines 182-188), this tells Git to only fetch objects necessary for the checkout, transferring file contents only when accessed. This dramatically reduces the amount of data transferred for large repositories.

Sparse Checkout for Large Repositories

For monorepos or repositories with many files, sparse checkout allows you to check out only specific directories via the sparse-checkout input. The implementation in src/git-source-provider.ts (lines 52-69) writes only matching files to the work-tree, reducing I/O and speeding up subsequent steps that only need a subset of the repository. You can also set sparse-checkout-cone-mode: true to enable cone mode for pattern matching.

Git-LFS Network Overhead

Enabling Git-LFS via lfs: true causes the action to execute an additional git lfs fetch after the initial checkout. The logic in src/git-source-provider.ts (lines 70-78) shows this adds a second network request. If your repository contains many large binary assets, this increases checkout time noticeably compared to standard Git objects.

Git Version Fallback Performance Impact

If the runner lacks Git 2.18 or newer, the action falls back to the GitHub REST API. As seen in src/git-source-provider.ts (lines 78-92), this triggers github-api-helper.downloadRepository to download a tarball of the repository. This method is slower for large repositories because it must be unpacked, and critically, it does not support submodules or LFS.

Automatic Garbage Collection Tuning

The action disables Git's automatic garbage collection by running git config gc.auto 0, as seen in src/git-source-provider.ts (lines 135-141). This prevents unexpected pauses during git fetch that could occur if GC triggered mid-run. While this avoids a mid-run delay, it may cause later runs to be slower if the repository accumulates many loose objects.

Authentication and Safe Directory Configuration

While negligible in cost, the action performs several configuration steps to ensure security and functionality. The configureAuth method in src/git-auth-helper.ts handles token and SSH key writing to the local Git config, while src/git-source-provider.ts (lines 46-63) adds the checkout directory to Git's safe.directory list. These operations enable subsequent authenticated Git commands without additional network round-trips.

Configuration Examples for Optimal Performance

Here are practical configurations based on the implementation in src/main.ts and related modules:


# Fast default checkout (shallow clone, no LFS)

- uses: actions/checkout@v7

# Fetch the entire repository history – useful for tools that need full Git history

- uses: actions/checkout@v7
  with:
    fetch-depth: 0   # loads all commits and tags

# Use a partial clone to avoid downloading large blobs

- uses: actions/checkout@v7
  with:
    filter: blob:none   # only fetch tree objects

    fetch-depth: 1      # still shallow, but no file data until needed

# Sparse checkout – only the src/ folder is needed

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

# Enable LFS (will add a second network request for large files)

- uses: actions/checkout@v7
  with:
    lfs: true

Summary

  • Default settings are fastest: The action defaults to fetch-depth: 1 with no LFS and no filter to minimize data transfer, as prioritized in src/git-source-provider.ts.
  • History completeness costs time: Setting fetch-depth: 0 or fetching all tags increases network and disk I/O significantly.
  • Partial and sparse checkouts reduce data: Using filter and sparse-checkout directives limits the working set to only necessary files, reducing transfer time for large repositories.
  • LFS adds network overhead: Each LFS-enabled checkout requires a separate fetch operation for large binaries, implemented in lines 70-78 of the source provider.
  • Git 2.18+ is required for optimal performance: Runners without modern Git fallback to slower REST API downloads via github-api-helper.ts that lack submodule support.

Frequently Asked Questions

Does actions/checkout download the entire repository by default?

No. By default, actions/checkout performs a shallow clone with fetch-depth: 1, downloading only the latest commit. This minimizes network usage and is implemented in src/git-source-provider.ts (lines 174-202) to optimize for CI/CD speed.

Why is my checkout step slow when using Git LFS?

When lfs: true is set, the action executes a separate git lfs fetch after the initial clone, as seen in src/git-source-provider.ts (lines 70-78). If your repository contains many large binary files, this secondary network request adds significant time compared to standard Git operations.

What happens if the runner doesn't have Git 2.18 installed?

The action falls back to the GitHub REST API via github-api-helper.downloadRepository, implemented in src/git-source-provider.ts (lines 78-92). This downloads a tarball instead of using Git commands, which is slower for large repositories and does not support submodules or LFS.

How does sparse-checkout improve actions/checkout performance?

Sparse checkout allows you to specify which files and directories to populate in the working tree using the sparse-checkout input. According to the implementation in src/git-source-provider.ts (lines 52-69), this reduces disk I/O and working tree size by skipping files that don't match your patterns, ideal for monorepos where you only need specific modules.

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 →