Performance Implications of Using `actions/checkout`: Optimizing GitHub Actions Speed

The performance of actions/checkout is determined by how much data it transfers and writes to disk, with the default shallow clone (fetch-depth: 1) optimized for speed while options like full history, LFS, or sparse checkout allow trading speed for completeness.

The actions/checkout action is the de facto standard for retrieving repository code in GitHub Actions workflows. Understanding the performance implications of using actions/checkout helps you optimize CI/CD pipelines by minimizing unnecessary network traffic and disk I/O. The action's behavior is controlled through several inputs defined in src/input-helper.ts and executed via the core logic in src/git-source-provider.ts.

Shallow Cloning with fetch-depth

By default, actions/checkout performs a shallow clone that fetches only the single commit triggering the workflow. In src/git-source-provider.ts (lines 174‑202), the action passes --depth=1 to the fetch command when fetch-depth defaults to 1, minimizing network traffic and disk I/O.

Setting fetch-depth: 0 instructs the action to fetch the entire history for all branches and tags. This can add seconds to the checkout step and significantly increase storage use on the runner, making it suitable only for tools that require full Git history or semantic version calculations.


# Fast default checkout (shallow clone)

- uses: actions/checkout@v7

# Full history for tools requiring complete Git log

- uses: actions/checkout@v7
  with:
    fetch-depth: 0

Partial Clone Filtering

When a filter input is supplied, the action implements partial clone semantics. As implemented in src/git-source-provider.ts (lines 182‑188), the action passes --filter=blob:none to the fetch command, performing a partial clone that transfers only tree objects initially.

This dramatically reduces data transfer for large repositories containing substantial binary assets or extensive histories, deferring blob downloads until files are actually checked out. However, subsequent Git operations that access file contents may trigger additional network requests.

- uses: actions/checkout@v7
  with:
    filter: blob:none
    fetch-depth: 1

Sparse Checkout Patterns

The sparse checkout feature limits I/O by writing only matching files to the working tree. In src/git-source-provider.ts (lines 52‑69, 60‑66), the action configures sparse-checkout patterns using git sparse-checkout set when you provide the sparse-checkout input.

By specifying paths and optionally enabling sparse-checkout-cone-mode (the default), you can restrict the checkout to specific directories like src/ or docs/, drastically reducing disk writes and speeding up subsequent steps that only need a subset of the repository.

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

Git LFS Network Overhead

Enabling Git Large File Storage (LFS) introduces additional network requests. According to the implementation in src/git-source-provider.ts (lines 70‑78), when lfs: true is set, the action runs git lfs fetch after the initial checkout to download large binary assets.

For repositories containing many large files, this can noticeably increase checkout time. If your workflow does not require LFS files, explicitly setting lfs: false avoids this overhead. Note that LFS operations may be skipped automatically in certain sparse checkout configurations.


# Enable LFS (adds network request for large files)

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

Fallback to REST API

When the runner lacks Git 2.18 or later, the action falls back to the GitHub REST API. In src/git-source-provider.ts (lines 78‑92), the code detects the Git version and, if insufficient, invokes github-api-helper.downloadRepository to fetch a tarball.

This fallback is slower for large repositories because the entire tarball must be unpacked, and it lacks support for submodules and LFS. The src/github-api-helper.ts file implements this alternative download mechanism, making it a viable but performance-degraded option when Git is unavailable.

Background Configuration Optimizations

Several background behaviors in src/git-source-provider.ts affect long-term performance:

  • Garbage Collection Disabling (lines 135‑141): The action sets git config gc.auto 0 to prevent automatic garbage collection during the fetch operation. While this avoids unexpected mid-run pauses, repositories may accumulate loose objects over time, potentially slowing future runs if not managed.

  • Safe Directory Configuration (lines 46‑63): The action adds the checkout directory to Git’s safe.directory list via git config calls. This adds negligible overhead but ensures compatibility with container jobs.

  • Authentication Handling: In src/git-auth-helper.ts, the configureAuth method writes tokens or SSH keys to the local Git config and removes them in the post-step. These extra config writes are minimal but enable subsequent authenticated Git commands without additional network round-trips.

Summary

  • Default speed: The action optimizes for speed with shallow clones (fetch-depth: 1) and no LFS by default.
  • History costs: Full history (fetch-depth: 0) increases network transfer and storage proportionally to repository size.
  • Selective downloads: Partial clones (filter) and sparse checkouts reduce data transfer by deferring or excluding blob downloads.
  • Binary overhead: LFS adds a secondary fetch operation that scales with the size and quantity of large files.
  • Fallback penalty: REST API fallback provides compatibility when Git 2.18+ is unavailable but sacrifices performance and features.

Frequently Asked Questions

How does fetch-depth affect actions/checkout performance?

The fetch-depth parameter directly controls the amount of Git history transferred. A value of 1 (the default) creates a shallow clone fetching only the latest commit, minimizing network traffic and disk usage. Setting it to 0 fetches the complete history and all branches, which can increase checkout time by seconds or more depending on repository size, as implemented in the fetch logic of src/git-source-provider.ts.

What is the performance difference between partial clone and sparse checkout?

Partial clone (filter: blob:none) fetches all directory trees but defers downloading file contents until accessed, reducing initial transfer while maintaining full directory structure. Sparse checkout limits the working tree to specific paths, reducing both disk I/O and storage. Partial clone affects data transfer timing, while sparse checkout affects disk write operations and subsequent step performance.

Why is my checkout slow when using Git LFS?

When lfs: true is configured, the action executes an additional git lfs fetch command after the standard checkout, as seen in src/git-source-provider.ts lines 70‑78. This second network request downloads all large files tracked by LFS, which can significantly increase checkout duration for repositories containing numerous or sizable binary assets.

Does actions/checkout work without Git installed?

Yes, but with performance trade-offs. If the runner lacks Git 2.18 or later, the action falls back to downloading a repository tarball via the GitHub REST API using github-api-helper.downloadRepository. This fallback avoids Git installation but is slower for large repositories, does not support submodules, and cannot handle LFS files.

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 →