DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

pull_request 中 git branch 显示 detached HEAD

PR 工作流检出合并测试引用时可能处于 detached HEAD。区分读取源分支名、创建本地分支与检出源 SHA,保持测试输入和权限边界。

同一份脚本在分支上能读到分支名,放进 pull_request 工作流后,git branch --show-current 却没有输出,git status 显示 detached HEAD。如果脚本因此拒绝继续,要先确认它需要的是分支名称,还是必须工作在一个本地分支上。

Pull Request 的默认检出常用于测试源分支与目标分支合并后的结果。它可能对应 refs/pull/编号/merge,并不是源分支的普通本地分支。本文按 actions/checkout 4.2.2 的引用处理说明;detached HEAD 本身不代表源码没下载完整,也不代表认证失败。

先保留这次任务测试的提交

在 checkout 后查看:

git rev-parse HEAD
git branch --show-current
git status --short --branch

把提交号与任务事件对应起来。若任务目的是合并测试,不应为了让第二条有输出就换成源分支:换掉检出引用,也会换掉测试输入。

仅需要给日志、产物标签或工具参数提供源分支名时,可以从事件上下文取值,而不改变检出:

- name: Show source branch name
  env:
    PR_SOURCE_BRANCH: ${{ github.head_ref }}
  run: printf '%s\n' "$PR_SOURCE_BRANCH"

这段用于 pull_request 场景,github.head_ref 是名称,不是证明当前 HEAD 已经切到了那个分支。将值先交给环境变量再由 shell 引用,也避免把分支名直接拼进脚本代码。若复用到其他事件,要为没有 head_ref 的情况另设规则。

工具一定要本地分支时,只创建本地入口

有些版本工具不接受 detached HEAD,即使它只读取文件和提交信息。确认检出的提交正是要处理的输入、工作区干净,并且名称尚未占用后,可以在一次性 Runner 工作区创建本地分支:

git switch -c ci-inspect

ci-inspect 是示例本地名称,可换成项目工具接受且不与已有分支冲突的名字。它把当前提交挂到本地分支上,没有改变这个提交的内容,也没有把分支推送到 GitHub。

这一做法不能冒充真实源分支。若工具按分支名决定正式发布版本,必须先审查它的分支规则;随意换一个本地名字可能导致另一种版本错误。一次性工作区用完即丢弃;持续复用的自托管工作区还需按原 checkout 清理流程恢复,不要强制覆盖正在使用的同名分支。

确实要测试源提交时,同时指定仓库与 SHA

如果业务要求检查 PR 的源提交,而非合并测试结果,可以显式检出事件中的源仓库和确定的提交:

- uses: actions/checkout@v4.2.2
  with:
    repository: ${{ github.event.pull_request.head.repo.full_name }}
    ref: ${{ github.event.pull_request.head.sha }}
    persist-credentials: false

这段仍属于 pull_request 任务。来自 fork 的 PR,其源分支可能不在目标仓库里,所以不能只把 github.head_ref 当作目标仓库的分支名。私有源仓库是否可读,还取决于任务现有身份的实际权限。

按 SHA 检出通常仍会是 detached HEAD,这正是固定输入的结果。验收应检查 git rev-parse HEAD 与事件中的源 SHA 一致,并确认测试目标已被明确改为源提交;不能把“出现分支名”当成唯一成功标准。

这里的读取、命名与本地分支处理不需要推送。不要为消除 detached HEAD 改用 pull_request_target 执行不可信 PR 代码,也不要给 fork 工作流补发写令牌或仓库密钥。确需写回分支时,应另设经过权限和代码信任审查的流程。