37

I am new to jenkins/devops; I am following this example. When I locally do (from the terminal):

git rev-parse --abbrev-ref HEAD

I get the current branch's name. However from within Jenkinsfile, in the logs I am getting:

HEAD

Been researching online for a while and couldn't find the reason so far. What are potential causes for this outcome?

Additional Details

In my jenkinsfile, i am trying to get the current git branch's name (the one that triggered the webhook) and then pipe it inside 'git branch' command, so code is as follows:

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'
      }
....
}

In the line

sh 'echo BRANCH_NAME ${GIT_BRANCH_NAME}'

Returns HEAD

I found a way around this using git name-rev --name-only HEAD and modified the script code to:

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]
}

Now I get the right branch name and the steps work, but I would rather have a less hacky way of doing things.

What is the best method to achieve what I want to achieve using best practices?

PS I am not using multi-branching pipeline and the requirements were to not use multi-branching.

hfontanez
  • 5,774
  • 2
  • 25
  • 37
chad
  • 393
  • 1
  • 3
  • 5
  • 4
    On the Git side, you get a "detached HEAD" by checking out something that is not a branch name (e.g., is a tag name, or a remote-tracking name, or a raw hash ID). Once you have that, `git rev-parse --abbrev-ref HEAD` will just return `HEAD`. That particular set of Jenkins pipeline instructions look rather suspicious / wrong to me, but I'm no Jenkins expert. – torek Nov 03 '17 at 15:05
  • Please put the rest of the instructions, it looks like you are checking out the wrong source or in a wrong way cause as said by Torek you are in "detached HEAD", it would help to know what you were trying to checkout and what actually you are checking out.. – ivoruJavaBoy Nov 03 '17 at 17:01
  • @torek please check the updates I added in the question. Thank you for the help! – chad Nov 04 '17 at 13:45
  • @ivoruJavaBoy please check the updates I added in the question. Thank you for the help! – chad Nov 04 '17 at 13:45
  • as torek mentioned you are in detached HEAD state and use the solution mentioned by Vijay Ramaswamy worked. sometimes we just think too much and forget basics – cnu May 09 '18 at 15:52
  • This works without the LocalBranch option `git log -n1 --format='%H'` – datashaman Feb 26 '20 at 15:27

4 Answers4

22

I am probably late in responding, but there is potentially a simpler way. Ensure that you select "Check out to specific local branch" under additional behaviors within your Git configuration. This will ensure that git checks out to the exact branch you are tracking, and your original command "git rev-parse --abbrev-ref HEAD" will work fine.enter image description here

Vijay Ramaswamy
  • 246
  • 2
  • 6
  • 3
    I think the option is now called "`Check out to matching local branch`" – TT-- Jan 18 '19 at 17:41
  • This worked! I added the local-branch (same name), as explained in the comment above, to the jenkins project configuration. Probly this is connected with the behavior explained here: https://stackoverflow.com/a/45405121/1313116 – Webchen May 11 '21 at 12:55
5

The solution that I've found for this situation is:

checkout([$class: 'GitSCM', branches: [[name: '*/' + branch]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'LocalBranch', localBranch: "**"]], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'cred', url: 'git@bitbucket.org:repofolder/repo.git']]])

The key here is [$class: 'LocalBranch', localBranch: "**"]. It allows to checkout a branch not a revision.

The source for it is taken from here.

Oleksandr Bondarenko
  • 1,998
  • 1
  • 19
  • 22
5

Problem:

As torek mentioned, if you've checked out a commit (vs a branch) you are in a "detached HEAD" state (HEAD detached at 123abc).

Why?

--abbrev-ref returns a non-ambiguous short name of the objects name. The current object is the commit you checked out, not a branch. Further, git wouldn't be able to determine which branch you wanted anyway because the commit you checked out could easily live in multiple branches.

Solution:

I would use Vijay Ramaswamy's suggestion, however, you could also hard-code the branch name in your script:

env.GIT_BRANCH_NAME='my-branch-name'

or more simply

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

bkidd
  • 560
  • 7
  • 7
1

If you are using the multibranch pipeline, branch name should be available in the environment variables as env. BRANCH_NAME. you can use sh 'printenv' inside your step to print all the available environment variables

Kvk
  • 522
  • 5
  • 15