# How actions/checkout Handles Git LFS: Configuration, Performance, and Implementation

> actions/checkout handles Git LFS as an opt-in feature. Learn how it configures LFS, manages performance, and implements downloads for binary objects.

- Repository: [GitHub Actions/checkout](https://github.com/actions/checkout)
- Tags: deep-dive
- Published: 2026-08-30

---

**actions/checkout treats Git Large File Storage (LFS) as an opt-in feature controlled by the `lfs` input, automatically setting `GIT_LFS_SKIP_SMUDGE=1` when disabled to prevent downloads, and explicitly running `git lfs install` and `git lfs fetch` when enabled to retrieve binary objects.**

The `actions/checkout` repository provides the official GitHub Action for cloning repositories into workflow runners, including specialized handling for repositories using **Git LFS** to version large binary files. Understanding how this action manages LFS configuration—from input parsing to environment variable injection—helps optimize both workflow performance and network usage. This guide examines the TypeScript source code to explain the complete LFS implementation pipeline.

## Parsing the LFS Input Configuration

The journey begins with input validation. In [[`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts)](https://github.com/actions/checkout/blob/main/src/input-helper.ts#L139-L141), the action reads the boolean `lfs` input from the workflow YAML. If the user specifies `lfs: true`, the parsed result sets `result.lfs` to `true`; otherwise, it defaults to `false`. This boolean flag propagates through the entire checkout process, determining whether the action prepares the environment for large file handling.

## Disabling LFS Smudge for Performance

When LFS is disabled (the default), the action prioritizes speed and bandwidth conservation.

### GIT_LFS_SKIP_SMUDGE Environment Variable

In [[`src/git-command-manager.ts`](https://github.com/actions/checkout/blob/main/src/git-command-manager.ts)](https://github.com/actions/checkout/blob/main/src/git-command-manager.ts#L669-L675), the constructor receives the `lfs` flag. When this value is `false`, the manager immediately sets the environment variable `GIT_LFS_SKIP_SMUDGE=1`. This prevents Git from automatically downloading LFS objects during the checkout phase, ensuring that pointer files remain as small text references rather than triggering expensive network fetches for binary data.

## Installing and Fetching LFS Objects

When the user explicitly enables LFS, the action shifts to active LFS management through a three-stage process controlled by [[`src/git-source-provider.ts`](https://github.com/actions/checkout/blob/main/src/git-source-provider.ts)](https://github.com/actions/checkout/blob/main/src/git-source-provider.ts).

### LFS Installation Process

If `lfs` is `true`, the provider invokes `await git.lfsInstall()` during the setup phase (lines 69-73). Before proceeding, the command manager validates that the installed `git-lfs` binary meets the minimum version requirement of **2.1 or higher**, ensuring compatibility with modern LFS features and security patches.

### Fetching LFS Objects

After the repository reference resolves, the provider determines whether to fetch binary content. At lines 42-50, the code checks `if (settings.lfs && !settings.sparseCheckout)`. When both conditions are met, it executes `await git.lfsFetch(checkoutInfo.startPoint || checkoutInfo.ref)`, which downloads the actual large files referenced by the LFS pointers. This fetch occurs as a batch operation rather than per-file, significantly improving performance over lazy smudging.

### Sparse Checkout Interactions

When **sparse checkout** is enabled alongside LFS, the action deliberately skips the explicit `git lfs fetch` call. In this scenario, LFS objects fetch lazily during the checkout step itself, downloading only the binary files that match the sparse checkout paths. This prevents unnecessary bandwidth usage for large files excluded from the partial checkout scope.

## Workflow Configuration Examples

Configure LFS handling in your workflow using the `lfs` input parameter.

Default behavior excludes LFS objects:

```yaml
steps:
  - uses: actions/checkout@v4
    # LFS defaults to false; pointer files download without binary content

```

Enable full LFS support for repositories with binary assets:

```yaml
steps:
  - uses: actions/checkout@v4
    with:
      lfs: true
      # Installs git-lfs and fetches all binary objects

```

Combine LFS with sparse checkout for selective large file retrieval:

```yaml
steps:
  - uses: actions/checkout@v4
    with:
      lfs: true
      sparse-checkout: |
        assets/images
      # LFS objects fetch on-demand for specified paths only

```

## Summary

- **Input handling**: The `lfs` boolean is parsed in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts) and defaults to `false` for backward compatibility.
- **Performance optimization**: When disabled, `GIT_LFS_SKIP_SMUDGE=1` is set in [`src/git-command-manager.ts`](https://github.com/actions/checkout/blob/main/src/git-command-manager.ts) to prevent automatic downloads.
- **Installation**: Enabled LFS triggers `git.lfsInstall()` in [`src/git-source-provider.ts`](https://github.com/actions/checkout/blob/main/src/git-source-provider.ts) with version validation (≥2.1).
- **Fetching**: Binary objects download via `git.lfsFetch()` unless sparse checkout is active, which defers fetching to the checkout phase.
- **Testing**: The repository includes [`__test__/verify-lfs.sh`](https://github.com/actions/checkout/blob/main/__test__/verify-lfs.sh) for validating LFS behavior across different configuration scenarios.

## Frequently Asked Questions

### When should I enable LFS in actions/checkout?

Enable the `lfs: true` input when your repository contains Git LFS pointer files that workflow steps must access as actual binary content, such as compiled artifacts, media files, or large datasets. If your workflow only needs the pointer files (text references) or uses sparse checkout to limit file scope, keeping the default `false` improves speed and reduces bandwidth consumption.

### Does enabling LFS slow down the checkout process?

Enabling LFS adds two network operations: installing the `git-lfs` binary and fetching binary objects via `git lfs fetch`. While this increases checkout time compared to pointer-only downloads, the implementation in [`src/git-source-provider.ts`](https://github.com/actions/checkout/blob/main/src/git-source-provider.ts) optimizes performance by batch-fetching objects rather than downloading them individually during checkout. The `GIT_LFS_SKIP_SMUDGE=1` optimization when disabled ensures you only pay the performance cost when explicitly requested.

### How does actions/checkout handle LFS with sparse checkout?

When both `lfs: true` and `sparse-checkout` are specified, the action skips the explicit `git lfs fetch` step in [`src/git-source-provider.ts`](https://github.com/actions/checkout/blob/main/src/git-source-provider.ts). Instead, LFS objects download lazily as the sparse checkout extracts files from the index. This prevents fetching large files that reside outside the sparse checkout cone, optimizing both storage and network usage for monorepos containing substantial binary assets.

### What Git LFS version does actions/checkout require?

According to the validation logic in [`src/git-command-manager.ts`](https://github.com/actions/checkout/blob/main/src/git-command-manager.ts), `actions/checkout` requires Git LFS version **2.1 or higher**. The command manager checks the installed version during initialization and fails fast if the runner's environment contains an outdated binary, ensuring reliable operation of LFS commands used during the fetch phase.