86

I've create a jenkins pipeline and it is pulling the pipeline script from scm.
I set the branch specifier to 'all', so it builds on any change to any branch.

How do I access the branch name causing this build from the Jenkinsfile?

Everything I have tried echos out null except

sh(returnStdout: true, script: 'git rev-parse --abbrev-ref HEAD').trim()

which is always master.

Marco Roy
  • 4,004
  • 7
  • 34
  • 50
Alex Yurkowski
  • 1,676
  • 1
  • 12
  • 26
  • If you are using [GitHub Pull Request Builder](https://plugins.jenkins.io/ghprb/) plugin, you can use `${env.ghprbSourceBranch}` or even `${env.ghprbActualCommit}`. – Danijel Jul 18 '22 at 12:55

13 Answers13

90

Use multibranch pipeline job type, not the plain pipeline job type. The multibranch pipeline jobs do posess the environment variable env.BRANCH_NAME which describes the branch.

In my script..

stage('Build') {
    node {
        echo 'Pulling...' + env.BRANCH_NAME
        checkout scm
        
    }
}

Yields...

Pulling...master
t0r0X
  • 4,212
  • 1
  • 38
  • 34
James
  • 1,263
  • 2
  • 12
  • 12
  • 17
    This is actually just the name of the job, not of the git branch. This works as long as your jobs have the same name as your branches. –  Oct 26 '17 at 14:11
  • 2
    And also all these variables are defined on the Git plugin's page here under Environment Variables: https://plugins.jenkins.io/git – arjabbar Dec 28 '17 at 13:52
  • 1
    `env.BRANCH_NAME` is the name of the job?? – Danijel Jul 15 '22 at 13:43
  • 1
    @Danijel, yes, for Multibranch Pipelines, the name of the job is the name of the branch. The pipeline still has whatever name you give it, but it creates a job for each branch (each pattern that you enabled), and those job names are the branch names. – jimtut Aug 06 '22 at 03:25
42

If you have a jenkinsfile for your pipeline, check if you see at execution time your branch name in your environment variables.

You can print them with:

pipeline {
    agent any

    environment {
        DISABLE_AUTH = 'true'
        DB_ENGINE    = 'sqlite'
    }

    stages {
        stage('Build') {
            steps {
                sh 'printenv'
            }
        }
    }
}

However, PR 91 shows that the branch name is only set in certain pipeline configurations:

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 3
    Thanks, that was helpful. Looks like it is not in my environment variables. Is it possible to expose the branch that caused the build? – Alex Yurkowski Feb 22 '17 at 05:58
  • 4
    This is ridiculous that a file in the repo (the Jenkinsfile) would ever be expected to provide a hardcoded branch name. This makes the repo itself a disaster to manage. This needs fixing... – moodboom Oct 16 '18 at 19:12
38

A colleague told me to use scm.branches[0].name and it worked. I wrapped it to a function in my Jenkinsfile:

def getGitBranchName() {
    return scm.branches[0].name
}
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Attila123
  • 932
  • 8
  • 8
  • 3
    Tried that and got.. ...org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method BRANCH_NAME does not work and env.BRANCH_NAME returns null... – James May 14 '17 at 10:34
  • 5
    If you set the shared library as global you will not have security issues. The other way is to allow those security exceptions on the `Manage Jenkins > In Process Script Approval` – Chen Sep 11 '17 at 07:12
  • You can also whitelist that method – Lee Meador Jan 22 '18 at 17:11
  • 2
    WINNER. Works great! No shell execution. No initial need to checkout anything. Works on a different node context. Works on a plain project. Good stuff. – macetw May 06 '20 at 19:15
  • 3
    This works for me. How to find out the properties of the `scm` object? Is there any documentation for this object? Thanks. – Kok How Teh Jun 22 '20 at 01:27
  • Here you have the object specs: https://www.jenkins.io/doc/pipeline/steps/workflow-scm-step/ – Alessandro S. Feb 08 '21 at 18:27
  • Note this only works if you are using "Pipeline script from SCM", and not if your Pipeline script is in Jenkins itself. – trebor Sep 20 '22 at 17:30
21

For pipeline:

pipeline {
  environment {
     BRANCH_NAME = "${GIT_BRANCH.split("/")[1]}"
  }
}
Hung
  • 459
  • 5
  • 15
  • 5
    I have adapted your answer to make it work on simple pipeline and also on multibranch pipelines where there is not need to split `GIT_BRANCH` with this condition: `BRANCH_NAME = "${GIT_BRANCH.split("/").size() > 1 ? GIT_BRANCH.split("/")[1] : GIT_BRANCH}"` – Romain Nov 17 '20 at 12:42
  • 4
    To improve @Romain's comment further: `BRANCH_NAME = "${GIT_BRANCH.split('/').size() > 1 ? GIT_BRANCH.split('/')[1..-1].join('/') : GIT_BRANCH}"` – George L. Yermulnik May 12 '21 at 16:44
  • Take into consideration that branch names will always starts with `origin/`, an improved version for all scenarios : `branchName = "${env.GIT_BRANCH.split('/').size() == 1 ? env.GIT_BRANCH.split('/')[-1] : env.GIT_BRANCH.split('/')[1..-1].join('/')}"` – Manuel Lazo Feb 20 '23 at 19:04
13

For me this worked: (using Jenkins 2.150, using simple Pipeline type - not multibranch, my branch specifier: '**')

echo 'Pulling... ' + env.GIT_BRANCH

Output:

Pulling... origin/myBranch

where myBranch is the name of the feature branch

alex
  • 180
  • 1
  • 13
  • 2
    This doesn't work, the result is pulling null. This answer is only useable if you specify more than just your version number, for instance, are you using any plug-ins that do the magic for you? – chrillelundmark May 16 '19 at 06:16
  • @chrillelundmark I edited my answer after trying again... I did not install a plugin to help me with that purpose, otherwise I don't know what else I should specify... I guess there are not enough characters in one comment to write down all my plugins – alex May 16 '19 at 07:16
  • I am getting `PR-45=` as a value of env.GIT_BRANCH when my jenkins job is triggered from PR. Not something I'd expect – dgebert Sep 30 '21 at 07:59
  • 1
    That returns null for me using Jenkins 2.303.1 on Windows, simple pipeline. – andrew lorien Oct 13 '21 at 06:44
7

This is for simple Pipeline type - not multibranch. Using Jenkins 2.150.1

environment {
    FULL_PATH_BRANCH = "${sh(script:'git name-rev --name-only HEAD', returnStdout: true)}"
    GIT_BRANCH = FULL_PATH_BRANCH.substring(FULL_PATH_BRANCH.lastIndexOf('/') + 1, FULL_PATH_BRANCH.length())
  }

then use it env.GIT_BRANCH

ROOT
  • 11,363
  • 5
  • 30
  • 45
CyrexLt
  • 93
  • 1
  • 5
  • This works great for me on a macOS slave however on the Windows slave I always get 'null' returned when doing environment { FULL_PATH_BRANCH_WIN = "${bat(script:'@git name-rev --name-only HEAD', returnStdout: true)}" GIT_BRANCH_WIN = FULL_PATH_BRANCH_WIN.substring(FULL_PATH_BRANCH_WIN.lastIndexOf('/') + 1, FULL_PATH_BRANCH_WIN.length()) } – Rip-Off Mar 17 '20 at 16:56
  • org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: WorkflowScript: 234: unexpected token: name @ line 234, column 42. TH_BRANCH = “${sh(script:‘git name-rev - Did't worked for me – AnilS Jun 16 '20 at 10:05
  • FULL_PATH_BRANCH returns null for me using Jenkins 2.303.1 on Windows, simple pipeline. – andrew lorien Oct 13 '21 at 06:45
5

Switching to a multibranch pipeline allowed me to access the branch name. A regular pipeline was not advised.

Alex Yurkowski
  • 1,676
  • 1
  • 12
  • 26
  • Yes, reading https://github.com/jenkinsci/pipeline-model-definition-plugin/pull/91, you should see it in `BRANCH_NAME`. – VonC Feb 22 '17 at 07:44
5

Just getting the name from scm.branches is not enough if you've used a build parameter as a branch specifier, e.g. ${BRANCH}. You need to expand that string into a real name:

scm.branches.first().getExpandedName(env.getEnvironment())

Note that getEnvironment() must be an explicit getter otherwise env will look up for an environment variable called environment.

Don't forget that you need to approve those methods to make them accessible from the sandbox.

0neel
  • 383
  • 5
  • 11
5

To get git branch name in Jenkins, If it is a multibranch pipeline then we can easily use the env.GIT_BRANCH. But if it is a normal pipeline then we can use the SCM plugin object to retrieve the branch name.

The below code works for both normal as well as multibranch pipelines.

def branch_nem = scm.branches[0].name
if (branch_nem.contains("*/")) {
    branch_nem = branch_nem.split("\\*/")[1]
    }
echo branch_nem
Jay Reddy
  • 630
  • 7
  • 6
3

FWIW the only thing that worked for me in PR builds was ${CHANGE_BRANCH}

(may not work on master, haven't seen that yet)

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
hwjp
  • 15,359
  • 7
  • 71
  • 70
1

This is what worked for me for non-multi-branch pipeline with either setting SCM Branch Specifier (blank for 'any') to */branch_name or setting it to just branch_name:

BRANCH_NAME = "${GIT_BRANCH.split('/').size() > 1 ? GIT_BRANCH.split('/')[1..-1].join('/') : GIT_BRANCH}"
0

I might want to use env.CHANGE_BRANCH to get real branch name instead of jenkins job / PR name.

Alexey Antonenko
  • 2,389
  • 1
  • 18
  • 18
0

Based on the necessity when you are working with just Jenkins Pipelines, I created the following function in a Shared Library:

package org.helpers

class Helpers {
    static def getBranchName(String branchName){
        return branchName.split('/').size() == 1 ? branchName.split('/')[-1] : branchName.split('/')[1..-1].join('/')
    }
}

From the pipeline I accessed that static method (my shared library was registered with the name pipelines):

@Library("pipelines") _
def helper = org.helpers.Helpers
pipeline {
        agent any
        environment {
            branchName = helper.getBranchName("${env.GIT_BRANCH}")
        }
       stages {
         stage('test'){
           agent any
           steps {
             script { sh "echo 'branchName: ${branchName}'" }
           }
         }
       }
}
Manuel Lazo
  • 745
  • 7
  • 7