GitHub Actions Checkout Detached HEAD - Branch Name Empty in CI
actions/checkout deliberately checks out the exact commit SHA in a detached HEAD state, so there is no current branch. Scripts that read the branch name or push to "the current branch" break.
What this error means
After actions/checkout, git branch --show-current prints nothing and git symbolic-ref HEAD fails. A later git push with no explicit refspec errors because HEAD is not on a branch.
$ git branch --show-current
# (empty)
$ git push
fatal: You are not currently on a branch.Common causes
Checkout uses a detached HEAD by design
For pull_request and many events, actions/checkout checks out a merge or head commit by SHA, not a named local branch, so HEAD is detached.
Scripts assume a named branch exists
Tooling that calls git branch --show-current, git rev-parse --abbrev-ref HEAD, or pushes without a refspec relies on a current branch that detached HEAD does not provide.
How to fix it
Check out a real branch with ref:
Pass ref: to check out a named branch (use github.head_ref for PRs) so HEAD points at a branch you can push.
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref || github.ref_name }}Derive the branch from context, not git
- Use github.ref_name or github.head_ref from the workflow context instead of git branch --show-current.
- Push with an explicit refspec, for example git push origin HEAD:${{ github.head_ref }}.
- Avoid commands that assume HEAD is attached when you only need the SHA.
How to prevent it
- Read the branch from github.ref_name / github.head_ref rather than local git state.
- Set ref: when a job must commit or push to a named branch.
- Always push with an explicit source:destination refspec in CI.