Jenkinsfile: git rev-parse --abbrev-ref HEAD 返回 HEAD。

38

我是jenkins/devops的初学者; 我正在遵循这个例子。 当我在本地终端执行以下操作时:

git rev-parse --abbrev-ref HEAD

我获取当前分支的名称。但是,在Jenkinsfile中,日志中会得到:

HEAD

我已经在网上研究了一段时间,但到目前为止仍然找不到原因。这种结果的潜在原因是什么?

额外细节

在我的jenkinsfile中,我正在尝试获取当前git分支的名称(触发webhook的分支),然后将其传递到'git branch'命令中,代码如下:

pipeline {
agent {
    label 'ubuntu'
}
stages {
    stage('check') {
    steps {
            script {
               env.GIT_BRANCH_NAME=sh(returnStdout: true, script: "git rev-parse --abbrev-ref HEAD").trim()
            }

            sh 'echo BRANCH_NAME ${GIT_BRANCH_NAME}'
            git branch: GIT_BRANCH_NAME, credentialsId: '******', url: 'https://*****/*****/*****.git'
      }
....
}

在这条线上

sh 'echo BRANCH_NAME ${GIT_BRANCH_NAME}'

返回 HEAD

我发现可以通过使用 git name-rev --name-only HEAD 绕过这个问题,并修改了脚本代码:

script {
    env.GIT_BRANCH_PATH=sh(returnStdout: true, script: "git name-rev --name-only HEAD").trim()
    env.GIT_BRANCH_NAME=GIT_BRANCH_PATH.split('remotes/origin/')[1]
}
现在我已经得到了正确的分支名称并且步骤可以运行,但我更愿意以一种不那么hacky的方式来完成这些事情。 使用最佳实践,实现我想要达到的目标的最佳方法是什么? 附言:我没有使用多分支管道,并且要求不使用多分支。

4
在 Git 方面,如果你检出的不是一个分支名(例如标签名、远程跟踪名或原始哈希 ID),则会出现“游离 HEAD”。此时,git rev-parse --abbrev-ref HEAD 将只返回 HEAD。这一组 Jenkins 流水线指令对我来说看起来相当可疑/错误,但我并不是 Jenkins 专家。 - torek
请放置其余的指示,看起来您正在检查错误的源或以错误的方式进行检查,因为根据Torek所说,您处于“分离的HEAD”状态,了解您要尝试检出什么以及实际检出了什么将会有所帮助。 - ivoruJavaBoy
@torek,请检查我在问题中添加的更新。感谢您的帮助! - chad
@ivoruJavaBoy,请查看我在问题中添加的更新。感谢您的帮助! - chad
正如torek所提到的,您处于分离的HEAD状态,并且使用Vijay Ramaswamy提到的解决方案是有效的。有时候我们会想太多而忘记基础知识。 - cnu
这段程序可以在不使用 LocalBranch 选项的情况下正常运行:git log -n1 --format='%H' - datashaman
4个回答

22

我可能回复晚了,但有一个更简单的方法。确保在Git配置中的附加行为下选择"检出到特定本地分支"。这将确保git检出到您正在跟踪的确切分支,并且您原始的命令“git rev-parse --abbrev-ref HEAD”将正常工作。enter image description here


3
我认为该选项现在被称为“将其签出到匹配的本地分支”。 - TT--
这个可行!我按照上面的评论所解释的方式,将同名的本地分支添加到了Jenkins项目配置中。这可能与此处所解释的行为有关:https://dev59.com/RlcO5IYBdhLWcg3wsTnM#45405121 - Webchen

6

问题:

Torek提到,如果您检出了一个提交(而不是分支),则处于“detached HEAD”状态((HEAD detached at 123abc))。

为什么?

--abbrev-ref返回对象名称的非歧义简短名称。当前对象是您检出的提交,而不是分支。此外,Git 无法确定您想要哪个分支,因为您检出的提交可能存在于多个分支中。

解决方案:

我会使用Vijay Ramaswamy建议,但您也可以在脚本中硬编码分支名称:

env.GIT_BRANCH_NAME='my-branch-name'

或更简单地说:

git branch: 'my-branch-name',credentialsId: '******',url: 'https://*****/*****/*****.git'


5
我为这种情况找到的解决方案是:
checkout([$class: 'GitSCM', branches: [[name: '*/' + branch]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'LocalBranch', localBranch: "**"]], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'cred', url: 'git@bitbucket.org:repofolder/repo.git']]])

这里的关键是[$class: 'LocalBranch', localBranch: "**"]。它允许检出分支而不是修订版本。
它的源代码来自这里

1
如果您使用多分支流水线,则分支名称应作为env.BRANCH_NAME出现在环境变量中。您可以在步骤内使用sh 'printenv'打印所有可用的环境变量。

谢谢Kvk,我已经提到我没有使用多分支。 - chad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接