GitHub Actions
Git
Branch
Commit \`Hash\`
Automation

Getting current branch and commit hash in GitHub action

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In GitHub Actions, the current branch and commit hash are usually available without running Git commands at all. The simplest path is to use the workflow context values that GitHub already provides. The main nuance is that pull request workflows often expose both a merge ref and a source branch ref, so the "current branch" depends on which one you actually want.

Use Built-In Context Values First

For most workflows, the commit SHA is straightforward:

yaml
${{ github.sha }}

For the branch name, the modern short-name field is often the easiest:

yaml
${{ github.ref_name }}

Example workflow step:

yaml
1jobs:
2  show-meta:
3    runs-on: ubuntu-latest
4    steps:
5      - name: Print branch and sha
6        run: |
7          echo "branch=${{ github.ref_name }}"
8          echo "sha=${{ github.sha }}"

This works well for push events and many other common workflow triggers.

Understand ref, ref_name, and PR Branches

GitHub exposes several related values:

  • 'github.ref: full ref such as refs/heads/main'
  • 'github.ref_name: short name such as main'
  • 'github.sha: triggering commit SHA'
  • 'github.head_ref: source branch of a pull request'

The subtle part is pull requests. On a pull_request event, github.ref often points to a merge ref such as refs/pull/123/merge, while github.head_ref contains the actual source branch name from the contributor branch.

So for PR workflows, this is often the better branch expression:

yaml
${{ github.head_ref || github.ref_name }}

That means:

  • use head_ref when it exists
  • otherwise fall back to ref_name

Set Outputs for Later Steps

If you want to reuse the values across many steps, write them once into step outputs or environment variables.

yaml
1jobs:
2  build:
3    runs-on: ubuntu-latest
4    steps:
5      - name: Capture git metadata
6        id: meta
7        run: |
8          echo "branch=${{ github.head_ref || github.ref_name }}" >> "$GITHUB_OUTPUT"
9          echo "sha=${{ github.sha }}" >> "$GITHUB_OUTPUT"
10
11      - name: Use metadata
12        run: |
13          echo "Branch: ${{ steps.meta.outputs.branch }}"
14          echo "SHA: ${{ steps.meta.outputs.sha }}"

This is cleaner than repeating the same expression throughout a larger workflow.

Use Git Commands Only When the Checkout State Matters

Sometimes you need the branch or commit from the checked-out repository state rather than from the event metadata. In that case, make sure the repository has actually been checked out first.

yaml
1jobs:
2  inspect:
3    runs-on: ubuntu-latest
4    steps:
5      - uses: actions/checkout@v4
6
7      - name: Read branch and commit with git
8        run: |
9          git branch --show-current
10          git rev-parse HEAD

This can differ from raw workflow context in some PR cases, especially if the checkout action fetches a merge commit or detached HEAD.

Know Which SHA You Really Need

github.sha is the commit that triggered the workflow context, but that may not always mean "the tip of the source branch" in the way people expect.

Examples:

  • on push, it is usually the pushed commit
  • on pull_request, it may represent the merge commit GitHub created for testing
  • on workflow_dispatch, it depends on the ref used to start the workflow

If you specifically need the PR head commit, inspect the event payload fields or checkout configuration instead of assuming github.sha always means branch tip.

A Practical Safe Pattern

For many CI workflows, this pattern is enough:

yaml
env:
  BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
  COMMIT_SHA: ${{ github.sha }}

Then every step can reference:

bash
echo "$BRANCH_NAME"
echo "$COMMIT_SHA"

That keeps the logic centralized and makes later debugging easier.

Common Pitfalls

The biggest mistake is using github.ref and then forgetting it is a full ref, not just the branch name. Another is treating github.ref_name as the source branch for pull requests when the workflow actually needs github.head_ref. Developers also run Git commands before checkout and then wonder why branch information is missing or detached. Finally, github.sha can mean different commits depending on the event type, so it is worth checking the trigger when the exact commit identity matters.

Summary

  • Use ${{ github.sha }} for the triggering commit SHA in most workflows.
  • Use ${{ github.ref_name }} for the short ref name on standard branch events.
  • For pull requests, ${{ github.head_ref || github.ref_name }} is often the safer branch expression.
  • Store branch and SHA in outputs or environment variables if multiple steps need them.
  • Use Git commands only after checkout when you need the checked-out repository state.
  • Always interpret branch and SHA values in the context of the workflow event type.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.