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-depthdefaults to1, limiting access to commit history. - Missing metadata: Tags and LFS files require explicit
fetch-tags: trueandlfs: truesettings. - Empty submodules: Submodule directories populate only when
submodulesis set totrueorrecursive. - Version constraints: Sparse-checkout requires Git >= 2.25; safe-directory requires >= 2.18.
- Security blocks: Fork PR checkouts require
allow-unsafe-pr-checkout: trueonpull_request_target. - Credential handling:
persist-credentialsnow defaults tofalseto 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →