diff --git a/README.md b/README.md
index 9b6176d94..36f6465ce 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,11 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
     # Otherwise, uses the default branch.
     ref: ''
 
+    # The commit SHA to checkout. Used when ref is not specified or is ambiguous. This
+    # can be used as a replacement for ref, or alongside it to checkout a specific
+    # commit of the ref.
+    commit: ''
+
     # Personal access token (PAT) used to fetch the repository. The PAT is configured
     # with the local git config, which enables your scripts to run authenticated git
     # commands. The post-job step removes the PAT.
diff --git a/__test__/input-helper.test.ts b/__test__/input-helper.test.ts
index 9514cb42d..99187b691 100644
--- a/__test__/input-helper.test.ts
+++ b/__test__/input-helper.test.ts
@@ -144,4 +144,30 @@ describe('input-helper tests', () => {
     const settings: IGitSourceSettings = await inputHelper.getInputs()
     expect(settings.workflowOrganizationId).toBe(123456)
   })
+
+  it('accepts ref and commit', async () => {
+    inputs.ref = 'refs/pull/123/merge'
+    inputs.commit = '0123456789012345678901234567890123456789'
+    const settings: IGitSourceSettings = await inputHelper.getInputs()
+    expect(settings).toBeTruthy()
+    expect(settings.ref).toBeTruthy()
+    expect(settings.ref).toStrictEqual('refs/pull/123/merge')
+    expect(settings.commit).toBeTruthy()
+    expect(settings.commit).toStrictEqual(
+      '0123456789012345678901234567890123456789'
+    )
+  })
+
+  it('ref fallbacks to commit if ref is empty but commit is specified', async () => {
+    inputs.ref = ''
+    inputs.commit = '0123456789012345678901234567890123456789'
+    const settings: IGitSourceSettings = await inputHelper.getInputs()
+    expect(settings).toBeTruthy()
+    expect(settings.ref).toBeFalsy()
+    expect(settings.ref).toStrictEqual('')
+    expect(settings.commit).toBeTruthy()
+    expect(settings.commit).toStrictEqual(
+      '0123456789012345678901234567890123456789'
+    )
+  })
 })
diff --git a/action.yml b/action.yml
index 75d5ae2d8..0ec5365db 100644
--- a/action.yml
+++ b/action.yml
@@ -9,6 +9,11 @@ inputs:
       The branch, tag or SHA to checkout. When checking out the repository that
       triggered a workflow, this defaults to the reference or SHA for that
       event.  Otherwise, uses the default branch.
+  commit:
+    description: >
+      The commit SHA to checkout. Used when ref is not specified or is ambiguous.
+      This can be used as a replacement for ref, or alongside it to checkout a
+      specific commit of the ref.
   token:
     description: >
       Personal access token (PAT) used to fetch the repository. The PAT is configured
diff --git a/dist/index.js b/dist/index.js
index 9d959a9ee..06398b566 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -1748,7 +1748,11 @@ function getInputs() {
         const isWorkflowRepository = qualifiedRepository.toUpperCase() ===
             `${github.context.repo.owner}/${github.context.repo.repo}`.toUpperCase();
         // Source branch, source version
-        result.ref = core.getInput('ref');
+        result.commit = core.getInput('commit');
+        if (result.commit && !result.commit.match(/^[0-9a-fA-F]{40}$/)) {
+            throw new Error(`The commit SHA '${result.commit}' is not a valid SHA.`);
+        }
+        result.ref = core.getInput('ref') || result.commit;
         if (!result.ref) {
             if (isWorkflowRepository) {
                 result.ref = github.context.ref;
diff --git a/src/input-helper.ts b/src/input-helper.ts
index 059232f5c..de6463612 100644
--- a/src/input-helper.ts
+++ b/src/input-helper.ts
@@ -57,7 +57,12 @@ export async function getInputs(): Promise<IGitSourceSettings> {
     `${github.context.repo.owner}/${github.context.repo.repo}`.toUpperCase()
 
   // Source branch, source version
-  result.ref = core.getInput('ref')
+  result.commit = core.getInput('commit')
+  if (result.commit && !result.commit.match(/^[0-9a-fA-F]{40}$/)) {
+    throw new Error(`The commit SHA '${result.commit}' is not a valid SHA.`)
+  }
+
+  result.ref = core.getInput('ref') || result.commit
   if (!result.ref) {
     if (isWorkflowRepository) {
       result.ref = github.context.ref