# How to Checkout a Pull Request with actions/checkout: 4 Methods Explained

> Checkout a pull request with actions/checkout using four methods. Learn to set ref for HEAD commits, handle forked PRs, and ensure safe checks.

- Repository: [GitHub Actions/checkout](https://github.com/actions/checkout)
- Tags: how-to-guide
- Published: 2026-07-17

---

**To checkout a pull request with actions/checkout, set the `ref` input to `${{ github.event.pull_request.head.sha }}` for the HEAD commit, or use `${{ github.head_ref }}` for closed events; for forked PRs in unsafe contexts like `pull_request_target`, you must additionally set `allow-unsafe-pr-checkout: true` after security review.**

The `actions/checkout` repository is the official GitHub Action for retrieving repository code in GitHub Actions workflows. When configuring workflows to checkout a pull request with actions/checkout correctly, you must understand that the default behavior retrieves the merge commit rather than the actual PR head, which affects how you configure the `ref` parameter.

## Default Behavior: The Merge Commit

Without specifying the `ref` input, `actions/checkout` defaults to `$GITHUB_SHA`. For a `pull_request` event, this environment variable contains the **merge commit** that GitHub automatically creates between the PR branch and the base branch. This merge commit represents the state of the code if the PR were merged at that moment.

According to the actions/checkout source code, the default `ref` value is defined in [[`action.yml`](https://github.com/actions/checkout/blob/main/action.yml)](https://github.com/actions/checkout/blob/main/action.yml) and resolves to the event's reference when unspecified.

## Method 1: Checkout the PR HEAD Commit

To retrieve the exact commit from the source branch (the "head" commit) rather than the merge commit, you must explicitly set the `ref` input to `${{ github.event.pull_request.head.sha }}`.

This configuration points the checkout directly to the forked branch's latest commit, bypassing the temporary merge commit entirely. The actions/checkout README documents this specific pattern under the section *"Checkout pull request HEAD commit instead of merge commit"* [[README § PR HEAD](https://github.com/actions/checkout/blob/main/README.md#checkout-pull-request-head-commit-instead-of-merge-commit)].

## Method 2: Checkout Forked PRs in Unsafe Contexts

When workflows run on `pull_request_target` or `workflow_run` events, the runner executes in the context of the **base repository** using the repository's `GITHUB_TOKEN`. By default, the action refuses to checkout code from forked pull requests in these contexts to prevent "pwn request" vulnerabilities where malicious code could access base repository secrets.

According to the actions/checkout source code, the security guard implementation resides in [[`src/unsafe-pr-checkout-helper.ts`](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts)](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts). This helper validates whether the PR originates from a fork and throws an error unless you explicitly opt-in by setting `allow-unsafe-pr-checkout: true` in your workflow configuration.

The input handling logic 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) reads this boolean flag and passes it to the validation helper. Only after this verification does the action proceed with the git operations.

## Method 3: Checkout on Closed Events

For workflows triggered by `pull_request` events with type `closed`, you must still specify the `ref` input because the checkout runs in detached HEAD mode with no active branch reference. Use `${{ github.head_ref }}` to reference the source branch name, or specify the exact SHA.

The actions/checkout README documents this requirement in the *"Checkout pull request on closed event"* section [[README § Closed PR](https://github.com/actions/checkout/blob/main/README.md#checkout-pull-request-on-closed-event)].

## Implementation Architecture

The checkout process follows this execution flow:

1. **Input Resolution**: The workflow passes inputs to the JavaScript entry point, where [[`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) normalizes the `ref` and `allow-unsafe-pr-checkout` values.

2. **Security Validation**: If the workflow runs in `pull_request_target` or `workflow_run` contexts and the PR originates from a fork, [[`src/unsafe-pr-checkout-helper.ts`](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts)](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts) validates the request. It terminates the action with an error unless `allow-unsafe-pr-checkout` is set to `true`.

3. **Git Execution**: After validation, the action constructs and executes the appropriate `git fetch` and `git checkout` commands based on the resolved reference.

4. **Workspace Preparation**: The repository is placed under `$GITHUB_WORKSPACE`, ready for subsequent workflow steps.

## Code Examples

### Checkout the HEAD commit of a standard PR

```yaml
- uses: actions/checkout@v7
  with:
    ref: ${{ github.event.pull_request.head.sha }}

```

### Checkout a forked PR in pull_request_target (unsafe context)

```yaml
- uses: actions/checkout@v7
  with:
    ref: ${{ github.event.pull_request.head.sha }}
    allow-unsafe-pr-checkout: true  # ⚠️ Review security implications first

```

### Checkout a PR on the closed event

```yaml
on:
  pull_request:
    types: [closed]

jobs:
  cleanup:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
        with:
          ref: ${{ github.head_ref }}  # Source branch name

```

## Summary

- **Default behavior**: Without `ref`, the action checks out the merge commit (`$GITHUB_SHA`), not the PR head.
- **PR HEAD checkout**: Use `ref: ${{ github.event.pull_request.head.sha }}` to get the exact source branch commit.
- **Forked PR security**: In `pull_request_target` or `workflow_run` contexts, fork PRs are blocked unless `allow-unsafe-pr-checkout: true` is set, as enforced by [[`src/unsafe-pr-checkout-helper.ts`](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts)](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts).
- **Closed events**: Explicitly set `ref` to `${{ github.head_ref }}` when handling `closed` event types.

## Frequently Asked Questions

### What is the difference between the merge commit and HEAD commit in a PR checkout?

The **merge commit** is a temporary commit GitHub creates that merges the PR branch into the base branch, representing the post-merge state. The **HEAD commit** is the exact last commit on the source branch of the pull request. Use `ref: ${{ github.event.pull_request.head.sha }}` to checkout the HEAD, or leave `ref` unspecified to get the merge commit.

### Why am I getting an error when trying to checkout a forked pull request?

The action blocks checkouts of forked PRs in `pull_request_target` or `workflow_run` contexts to prevent privilege escalation attacks. As implemented in [[`src/unsafe-pr-checkout-helper.ts`](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts)](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts), you must set `allow-unsafe-pr-checkout: true` to override this protection, but only after reviewing the security implications of exposing base repository secrets to fork code.

### Can I checkout a pull request after it has been closed?

Yes, but you must explicitly specify the `ref` input because the closed event runs in detached HEAD mode. Use `ref: ${{ github.head_ref }}` to checkout the source branch name, or provide the specific SHA. This pattern is documented in the README's closed event section.

### Is it safe to use `allow-unsafe-pr-checkout: true`?

This setting is safe only when you have reviewed the code in the pull request and trust the changes, as it allows forked PR code to run in a context that has access to your repository's secrets. The [[`src/unsafe-pr-checkout-helper.ts`](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts)](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts) file implements this guard specifically to prevent accidental exposure of sensitive tokens to potentially malicious fork code.