Actions/Checkout Limitations: 10 Critical Constraints Every GitHub User Must Know

The actions/checkout GitHub Action enforces shallow clones by default, omits tags and Git LFS objects unless explicitly enabled, blocks forked pull request checkouts without security opt-in, and requires Git version 2.25 or higher for sparse-checkout functionality.

The actions/checkout action is the official GitHub Action for pulling repository code into CI/CD workflows. While it handles standard cloning automatically, the source code in actions/checkout reveals several built-in limitations that can trigger build failures when you need full Git history, large files, or access to external repositories.

Shallow Clone by Default (fetch-depth)

By default, actions/checkout performs a shallow clone that retrieves only the single commit that triggered the workflow run. In src/input-helper.ts (lines 31-38), the fetch-depth input defaults to 1, meaning your workflow has no access to file history, previous commits, or diff information.

This optimization speeds up checkout times but breaks workflows that rely on git log, git describe, or semantic versioning tools that scan tags.

- uses: actions/checkout@v7
  with:
    fetch-depth: 0  # Fetch complete history instead of single commit

Tags and LFS Objects Omitted by Default

The action excludes annotated tags and Git LFS (Large File Storage) objects unless you explicitly enable them. According to src/input-helper.ts (lines 12-15), fetch-tags defaults to false, and lines 22-25 show lfs also defaults to false.

Without these settings, workflows requiring version tags or binary assets stored in LFS will fail with "file not found" or "smudge filter" errors.

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

Submodule Directories Remain Empty

Submodules are not initialized automatically. The input parsing in src/input-helper.ts (lines 26-35) sets submodules to false by default, leaving submodule directories empty on the runner. You must explicitly request recursive or single-level submodule checkout.

- uses: actions/checkout@v7
  with:
    submodules: recursive  # Options: 'true' or 'recursive'

Sparse Checkout Requires Git >= 2.25

The sparse-checkout feature, which allows downloading only specific directories, requires Git version 2.25 or higher. The validation logic in src/input-helper.ts (lines 94-104) checks for this version requirement, and the action will fail on older self-hosted runners.

Additionally, sparse-checkout operates in "cone mode" by default (faster, path-pattern matching), but you can disable this for legacy behavior using sparse-checkout-cone-mode: false.

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

Fork PR Checkouts Blocked Without Security Opt-in

For security reasons, the action refuses to checkout code from forked pull requests when running on pull_request_target or workflow_run events. The enforcement logic in src/unsafe-pr-checkout-helper.ts (lines 13-80) validates the repository origin and blocks the operation unless you explicitly set allow-unsafe-pr-checkout: true.

This prevents potential credential leakage when untrusted code executes in privileged workflow contexts.

- uses: actions/checkout@v7
  with:
    allow-unsafe-pr-checkout: true  # Only after security review

Credential Persistence Changes

The default value for persist-credentials changed from true to false in recent versions. As defined in src/input-helper.ts (lines 49-52), credentials are no longer persisted to the Git config by default. This prevents the GitHub token from being written to disk, but if you need downstream steps to perform authenticated Git operations, you must explicitly enable it.

- uses: actions/checkout@v7
  with:
    persist-credentials: true  # Required for subsequent authenticated git commands

Cross-Repository Access Requires PAT

The built-in github.token can only read the current repository. To checkout a different private repository, you must provide a Personal Access Token (PAT) with appropriate scopes via the token input. The action does not support checking out repositories from arbitrary Git hosts like Bitbucket or GitLab; it only works against GitHub.com or GitHub Enterprise Server (GHES) instances as specified by the github-server-url input.

- uses: actions/checkout@v7
  with:
    repository: my-org/other-private-repo
    token: ${{ secrets.PAT }}

Runtime and Version Requirements

The action now runs on Node 24 and requires Git version 2.18 or higher for features like safe-directory handling. Version checks in src/git-version.ts enforce these requirements, meaning older self-hosted runners may fail to execute the action even if they support basic Git operations.

Summary

  • Shallow clones: fetch-depth defaults to 1, limiting access to commit history.
  • Missing metadata: Tags and LFS files require explicit fetch-tags: true and lfs: true settings.
  • Empty submodules: Submodule directories populate only when submodules is set to true or recursive.
  • Version constraints: Sparse-checkout requires Git >= 2.25; safe-directory requires >= 2.18.
  • Security blocks: Fork PR checkouts require allow-unsafe-pr-checkout: true on pull_request_target.
  • Credential handling: persist-credentials now defaults to false to prevent token leakage.
  • Access restrictions: Cross-repository and private repo access requires a PAT; platform limited to GitHub/GHES.

Frequently Asked Questions

How do I fetch the full Git history in actions/checkout?

Set fetch-depth: 0 in your workflow configuration. By default, the action only fetches the single commit that triggered the workflow (defined in src/input-helper.ts). Setting this to 0 retrieves all history and tags (if combined with fetch-tags: true), enabling commands like git log and git describe.

Why are my Git LFS files missing after checkout?

The lfs input defaults to false in src/input-helper.ts (lines 22-25). You must explicitly add lfs: true to your checkout step. Without this setting, LFS pointers remain as text files instead of downloading the actual binary content.

Can I checkout code from a forked pull request in a workflow_run event?

Not by default. The action blocks checkouts from forked repositories on workflow_run and pull_request_target events to prevent credential theft. You must set allow-unsafe-pr-checkout: true to override this protection, as implemented in src/unsafe-pr-checkout-helper.ts. Only enable this after reviewing the security implications of running untrusted code.

Does actions/checkout work with GitLab or Bitbucket repositories?

No. The action only supports GitHub.com and GitHub Enterprise Server instances. While you can specify a different server URL using the github-server-url input, the underlying authentication and API calls are specific to GitHub's platform. For other Git hosts, use native Git commands or host-specific actions.

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 →