# Understanding the Main and Post Phases in actions/checkout: A Complete Guide

> Explore the main and post phases in actions/checkout. Learn how this GitHub Action checks out repos, authenticates, and cleans up credentials for efficient workflow execution.

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

---

**The `actions/checkout` GitHub Action executes in two distinct phases: the Main phase runs at job start to handle repository checkout and authentication, while the Post phase automatically runs after job completion to remove persisted credentials and clean up temporary files.**

The `actions/checkout` action is one of the most widely used utilities in GitHub Actions workflows, but its execution model relies on a critical two-phase architecture that separates repository setup from secure cleanup. Understanding how these **main and post phases in actions/checkout** work together helps you manage authentication securely and troubleshoot credential-related issues in your CI/CD pipelines.

## What Are the Main and Post Phases in actions/checkout?

GitHub Actions supports lifecycle hooks that allow actions to run logic before and after the primary job steps. The `actions/checkout` implementation leverages this by splitting its operation into distinct main and post phases.

### Main Phase (Job Start)

The **Main phase** executes immediately when the `uses: actions/checkout` step runs in your workflow. According to the source code in [[`src/main.ts`](https://github.com/actions/checkout/blob/main/src/main.ts)](https://github.com/actions/checkout/blob/main/src/main.ts), this phase handles:

- **Input processing**: Reads all workflow inputs including `ref`, `repository`, `fetch-depth`, `submodules`, `lfs`, and `persist-credentials`
- **Authentication setup**: Configures Git PAT (Personal Access Token) or SSH key authentication based on provided secrets
- **Repository operations**: Executes the actual Git commands for cloning, fetching, sparse checkout, and submodule initialization
- **Credential persistence**: When `persist-credentials: true` is set, writes the authentication token to the local Git configuration so subsequent steps can access the repository

### Post Phase (Job Cleanup)

The **Post phase** executes automatically after all job steps complete, regardless of whether the job succeeded or failed. As defined in [[`action.yml`](https://github.com/actions/checkout/blob/main/action.yml)](https://github.com/actions/checkout/blob/main/action.yml) at line 118, this phase runs the compiled script at [`dist/index.js`](https://github.com/actions/checkout/blob/main/dist/index.js) to perform security-critical cleanup operations.

## How the Main Phase Works in Detail

When your workflow reaches the checkout step, [[`src/main.ts`](https://github.com/actions/checkout/blob/main/src/main.ts)](https://github.com/actions/checkout/blob/main/src/main.ts) orchestrates the repository setup through several key operations:

1. **Input validation**: The helper functions in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts) parse and validate workflow inputs
2. **Git configuration**: Sets up user name, email, and authentication headers in the local Git config
3. **Repository fetch**: Executes `git fetch` with the specified depth and ref, or performs a full clone if necessary
4. **Submodule handling**: If `submodules: recursive` is specified, initializes and updates nested repositories
5. **Credential storage**: When `persist-credentials` is enabled, stores the PAT in `.git/config` for use by later steps

```yaml
- name: Checkout with persisted credentials
  uses: actions/checkout@v4
  with:
    fetch-depth: 0
    persist-credentials: true  # Default behavior: token available to subsequent steps

    token: ${{ secrets.GITHUB_TOKEN }}

```

## How the Post Phase Cleans Up Credentials

The post-job cleanup is defined in the action metadata. The [[`action.yml`](https://github.com/actions/checkout/blob/main/action.yml)](https://github.com/actions/checkout/blob/main/action.yml) file specifies `post: dist/index.js`, which instructs GitHub Actions to execute the compiled cleanup script after the job finishes.

According to the architectural decision record in [[`adrs/0153-checkout-v2.md`](https://github.com/actions/checkout/blob/main/adrs/0153-checkout-v2.md)](https://github.com/actions/checkout/blob/main/adrs/0153-checkout-v2.md), the post phase performs these specific security tasks:

- **Removes the PAT**: Deletes the Personal Access Token from `.git/config` that was added during the main phase
- **Deletes SSH keys**: Removes any temporary SSH private keys added to the SSH agent
- **Cleans temporary files**: Removes files stored under `$RUNNER_TEMP` that were used during checkout
- **Resets Git config**: Restores Git configuration to its pre-checkout state

This automatic cleanup ensures that no secrets remain on the runner after your workflow completes, mitigating the risk of credential leakage to subsequent jobs or processes.

## Configuring Credential Persistence

You control whether the main phase persists credentials—and consequently whether the post phase has cleanup work to do—using the `persist-credentials` input.

```yaml
- name: Checkout without credential persistence
  uses: actions/checkout@v4
  with:
    persist-credentials: false  # Main phase skips writing token; Post phase has no credentials to clean

```

When `persist-credentials: false`, the main phase configures authentication only for the initial fetch operation without writing to the Git config. The post phase still runs but performs minimal cleanup since no credentials were persisted.

## Summary

- The **main phase** in `actions/checkout` runs at job start in [`src/main.ts`](https://github.com/actions/checkout/blob/main/src/main.ts) to handle inputs, authentication, and repository checkout operations.
- The **post phase** automatically executes after job completion via [`dist/index.js`](https://github.com/actions/checkout/blob/main/dist/index.js) (defined in [`action.yml`](https://github.com/actions/checkout/blob/main/action.yml)) to remove credentials and secure the runner.
- The `persist-credentials` input controls whether authentication tokens are written to the Git config during the main phase and subsequently cleaned up during the post phase.
- Architectural decisions documented in [`adrs/0153-checkout-v2.md`](https://github.com/actions/checkout/blob/main/adrs/0153-checkout-v2.md) mandate that the post phase specifically removes PATs and SSH keys to prevent secret leakage.

## Frequently Asked Questions

### What triggers the post phase in actions/checkout?

The post phase triggers automatically after all job steps complete, regardless of success or failure. The [[`action.yml`](https://github.com/actions/checkout/blob/main/action.yml)](https://github.com/actions/checkout/blob/main/action.yml) file defines `post: dist/index.js`, which GitHub Actions invokes as a post-job hook. You do not need to add explicit configuration to trigger this cleanup.

### How do I prevent actions/checkout from persisting credentials?

Set `persist-credentials: false` in your workflow configuration. This prevents the main phase from writing the token to `.git/config`, meaning the post phase will have no credentials to remove. This is useful when you want to ensure no authentication data touches disk during the workflow execution.

### Why does the post phase matter for security?

The post phase removes sensitive authentication data—including PATs and SSH keys—that the main phase adds to the Git configuration. Without this cleanup step, subsequent jobs running on the same self-hosted runner could access these credentials. As documented in the project's ADR, this automatic cleanup ensures secrets are available only for the duration of the current job.

### Can I disable the post phase cleanup?

No, you cannot disable the post phase when using `actions/checkout`. The cleanup hook is hardcoded in [`action.yml`](https://github.com/actions/checkout/blob/main/action.yml) and executes automatically. However, if you set `persist-credentials: false`, the cleanup operations will find nothing to remove, effectively making the post phase a no-op while still satisfying the security requirements.