Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-33984

Git plugin sets wrong branch name GIT_BRANCH (more than 2 branches with same SHA1)

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Major Major
    • git-plugin
    • None
    • Production

      Git plugin ver: 2.4.4

      In jenkins job we configure Git plugin ->
      Branches to build/Branch specifier: origin/ready/**

      Developer pushes code to central git repository, which Jenkins check into 2 branches:
      git push origin bugfix:sergey/bugfix
      git push origin bugfix:ready/bugfix

      When Jenkins job kicks in, it provides this output:

      14:01:36 > git branch -a -v --no-abbrev --contains 24ef859065480d5ac965652cfce8a0dd959fd082 # timeout=10
      14:01:36 Checking out Revision 24ef859065480d5ac965652cfce8a0dd959fd082 (origin/sergey/bugfix, origin/ready/bugfix)
      ..
      ..

      14:01:36 HOME=/var/lib/jenkins
      14:01:36 GIT_BRANCH=origin/sergey/bugfix
      14:01:36 EXECUTOR_NUMBER=1

      As you can see GIT_BRANCH got set to "origin/sergey/bugfix"
      and this is wrong because we asked for branch to match origin/ready/**

      This causes problems in our build process

          [JENKINS-33984] Git plugin sets wrong branch name GIT_BRANCH (more than 2 branches with same SHA1)

          Mark Waite added a comment -

          You might try using the local branch extension that was added in git plugin 2.4.4. It may be able to checkout the branch which matches the name from the branch spec, rather than reporting the name of the first branch mentioned in the rev-parse output.

          Mark Waite added a comment - You might try using the local branch extension that was added in git plugin 2.4.4. It may be able to checkout the branch which matches the name from the branch spec, rather than reporting the name of the first branch mentioned in the rev-parse output.

          Sergey Leonovich added a comment - - edited

          I cannot seem to find "local branch extension that was added in git plugin 2.4.4" you mentioning

          Sergey Leonovich added a comment - - edited I cannot seem to find "local branch extension that was added in git plugin 2.4.4" you mentioning

          We're seeing this behaviour as well. Happens fairly frequently because we use GitFlow. For the first build of a release branch both the release branch and develop point to the same commit. Unfortunately we cannot set the local branch name because we don't know in advance what the branch name is going to be, e.g. the user might be building release/1.2.0, but we can't set that configuration in jenkins because that number will be changing.

          Normally this might not be that important but in our case we're using GitVersion (https://github.com/GitTools/GitVersion) which calculates the version number based on the state of the repository and part of that is the branch you're on and, in case of release and hotfix branches, the 'version' of the branch. So we really need jenkins to checkout the correct branch (and ideally into a local branch with the same name)

          Petrik van der Velde added a comment - We're seeing this behaviour as well. Happens fairly frequently because we use GitFlow. For the first build of a release branch both the release branch and develop point to the same commit. Unfortunately we cannot set the local branch name because we don't know in advance what the branch name is going to be, e.g. the user might be building release/1.2.0, but we can't set that configuration in jenkins because that number will be changing. Normally this might not be that important but in our case we're using GitVersion ( https://github.com/GitTools/GitVersion ) which calculates the version number based on the state of the repository and part of that is the branch you're on and, in case of release and hotfix branches, the 'version' of the branch. So we really need jenkins to checkout the correct branch (and ideally into a local branch with the same name)

          We are seeing the same behavior.
          Git plugin ver: 2.6.0
          In jenkins job we configure Git plugin ->
          Branches to build/Branch specifier: origin/release**

          jenkins kics off job -

          Checking out Revision 7eb9d66f902e673005daa3d428634ce04805eea5 (origin/develop, origin/release/xyz) and sets the ${GIT_BRANCH} to origin/develop, whereas we asked for only origin/release**

          any ideas on fixing this?

          Pragya Jaiswal added a comment - We are seeing the same behavior. Git plugin ver: 2.6.0 In jenkins job we configure Git plugin -> Branches to build/Branch specifier: origin/release** jenkins kics off job - Checking out Revision 7eb9d66f902e673005daa3d428634ce04805eea5 (origin/develop, origin/release/xyz) and sets the ${GIT_BRANCH} to origin/develop, whereas we asked for only origin/release** any ideas on fixing this?

          Mark Waite added a comment -

          Sorry pjaiswal, but I don't have any ideas for fixing it. I suspect that the git plugin has a separation between the logic which decides which branches should be checked for changes, and which branches should be built. The git plugin generally assumes that once a SHA1 or one of its successors has been built, it does not need to be built again.

          I realize that is incorrect in this case, since the user clearly stated to check one set of branches, and the plugin incorrectly performed the checkout of a branch which was not in that set of branches.

          You might consider using one or more custom "refspec" values in the advanced section of the job's "Repositories" section. It may be that you can avoid the checkout of the develop branch by creating one or more refspecs which exclude the develop branch from being cloned into the repository. If the develop branch is not cloned into the repository, the plugin probably won't choose it as the branch to checkout.

          If you use the custom refspec technique, you'll also need to add the "Advanced clone option" (from "Additional Behaviours") to "Honor refspec on initial clone". The default behavior is to clone all remote refspecs, even if a custom refspec is provided. That default behavior is retained so that we don't break compatibility with some existing use cases.

          Mark Waite added a comment - Sorry pjaiswal , but I don't have any ideas for fixing it. I suspect that the git plugin has a separation between the logic which decides which branches should be checked for changes, and which branches should be built. The git plugin generally assumes that once a SHA1 or one of its successors has been built, it does not need to be built again. I realize that is incorrect in this case, since the user clearly stated to check one set of branches, and the plugin incorrectly performed the checkout of a branch which was not in that set of branches. You might consider using one or more custom "refspec" values in the advanced section of the job's "Repositories" section. It may be that you can avoid the checkout of the develop branch by creating one or more refspecs which exclude the develop branch from being cloned into the repository. If the develop branch is not cloned into the repository, the plugin probably won't choose it as the branch to checkout. If you use the custom refspec technique, you'll also need to add the "Advanced clone option" (from "Additional Behaviours") to "Honor refspec on initial clone". The default behavior is to clone all remote refspecs, even if a custom refspec is provided. That default behavior is retained so that we don't break compatibility with some existing use cases.

          Thanks Mark for the explanation. Could you please elaborate on the using custom refspecs? I eventually have to extend my Jenkins job for the following Branch specifiers:

          Branch specifier 1 - origin/develop
          Branch Specifier 2 - origin/release**

          (But would like to ignore these set of branches - origin/feature** and origin/bugfix**)

          Would that require specifying multiple refspecs? Would you have a screenshot to share?

          Pragya Jaiswal added a comment - Thanks Mark for the explanation. Could you please elaborate on the using custom refspecs? I eventually have to extend my Jenkins job for the following Branch specifiers: Branch specifier 1 - origin/develop Branch Specifier 2 - origin/release** (But would like to ignore these set of branches - origin/feature** and origin/bugfix**) Would that require specifying multiple refspecs? Would you have a screenshot to share?

          Mark Waite added a comment - - edited

          Yes, you would need to specify multiple refspecs behind the advanced button of the repository definition for the job. I assume your

          origin/release**

          branch specifier really means

          origin/release/**

          .
          I think your refspec should look like this:

          +refs/heads/develop:refs/remotes/origin/develop
          +refs/heads/release/*:refs/remotes/origin/release/*
          

          The git refspecs documentation gives a very good review of the strengths and weaknesses of refspec definition.

          Mark Waite added a comment - - edited Yes, you would need to specify multiple refspecs behind the advanced button of the repository definition for the job. I assume your origin/release** branch specifier really means origin/release/** . I think your refspec should look like this: +refs/heads/develop:refs/remotes/origin/develop +refs/heads/release/*:refs/remotes/origin/release/* The git refspecs documentation gives a very good review of the strengths and weaknesses of refspec definition.

          Pragya Jaiswal added a comment - - edited

          Thanks Mark. that does resolve my issue. However, how can I extend the functionality of my jenkins job -
          My jenkins job tracks multiple branches and triggers builds if there are changes to any of those branches. For example I have multiple branch specifiers added to my job -
          origin/release**
          origin/develop

          The job is working fine when there are merges to any of these branches.In some cases I want to be able to specify/input a branch to pull the source and build from. How can I accomplish that considering I have the branch specifiers already set? Any ideas on implementing this?

          I tried a couple of things -

          1. Added a build parameters called $BranchOverride and tried 2 test cases. case 1 - Setting the default value to "None" with 3 branch specifiers for release/* , develop and $BranchOverride. Case 2 - setting the default value to origin/develop and set 2 branch specifiers release/ * and $BranchOverride. Both the cases, when I manually input a branch, it doesn't work as I expect it to.

          2. Instead of specifying multiple Branch specifiers, I created a string Parameter $BranchOverride and set the value as a regex : (?=(origin/develop|origin/release)).*
          When I push to one of my release branch, it triggers a build (and multiple consecutive builds) for multiple branches, even those that dont have any push. I see this is the log -

          Seen 1,116 remote branches
          Multiple candidate revisions
          Scheduling another build to catch up with ABC_TestJob
          Checking out Revision 366bdc3674103e4b2479d75508f3971c6f080591 (origin/release/xyz)

          I must add that in the test case where I added a regex, manually giving the branch input works but the automated trigger doesnt behave as expected. Maybe I am not understanding the behavior correctly, am not sure.

          Pragya Jaiswal added a comment - - edited Thanks Mark. that does resolve my issue. However, how can I extend the functionality of my jenkins job - My jenkins job tracks multiple branches and triggers builds if there are changes to any of those branches. For example I have multiple branch specifiers added to my job - origin/release** origin/develop The job is working fine when there are merges to any of these branches.In some cases I want to be able to specify/input a branch to pull the source and build from. How can I accomplish that considering I have the branch specifiers already set? Any ideas on implementing this? I tried a couple of things - 1. Added a build parameters called $BranchOverride and tried 2 test cases. case 1 - Setting the default value to "None" with 3 branch specifiers for release/* , develop and $BranchOverride. Case 2 - setting the default value to origin/develop and set 2 branch specifiers release/ * and $BranchOverride. Both the cases, when I manually input a branch, it doesn't work as I expect it to. 2. Instead of specifying multiple Branch specifiers, I created a string Parameter $BranchOverride and set the value as a regex : (?=(origin/develop|origin/release)).* When I push to one of my release branch, it triggers a build (and multiple consecutive builds) for multiple branches, even those that dont have any push. I see this is the log - Seen 1,116 remote branches Multiple candidate revisions Scheduling another build to catch up with ABC_TestJob Checking out Revision 366bdc3674103e4b2479d75508f3971c6f080591 (origin/release/xyz) I must add that in the test case where I added a regex, manually giving the branch input works but the automated trigger doesnt behave as expected. Maybe I am not understanding the behavior correctly, am not sure.

          Matthew Smith added a comment - - edited

          +1 for this issue

          In my case, GIT_BRANCH is not even getting set to a branch name. It is getting set to the name of a tag in the repo.

          Matthew Smith added a comment - - edited +1 for this issue In my case, GIT_BRANCH is not even getting set to a branch name. It is getting set to the name of a tag in the repo.

          Dan Porter added a comment -

          This is still a problematic issue. It seems that $GIT_BRANCH is set to whatever the first identified branch is for that commit, rather than the triggering branch received by Jenkins.

          Example of feature/awful, as the only branch pointing at this id, working:

          Checking out Revision d0903cd1d7fab333f84fa8094af14552cc17355c (origin/feature/awful)
          GIT_BRANCH is 'origin/feature/awful'

          Example of master, of which develop is also pointing at this commit id, not working:

          Checking out Revision 62e085f7ab8163c305bef91e07314a5f09d2ed5a (origin/develop, origin/master)
          GIT_BRANCH is 'origin/develop'

          Dan Porter added a comment - This is still a problematic issue. It seems that $GIT_BRANCH is set to whatever the first identified branch is for that commit, rather than the triggering branch received by Jenkins. Example of feature/awful , as the only branch pointing at this id, working: Checking out Revision d0903cd1d7fab333f84fa8094af14552cc17355c (origin/feature/awful) GIT_BRANCH is 'origin/feature/awful' Example of master , of which develop is also pointing at this commit id, not working: Checking out Revision 62e085f7ab8163c305bef91e07314a5f09d2ed5a (origin/develop, origin/master) GIT_BRANCH is 'origin/develop'

          Jon Starbird added a comment -

          For us, the job will build the correct branch and if you look at the Environment Variables after the build the GIT_BRANCH variable is set to the correct value but if you use the GIT_BRANCH variable for Email for example the value is wrong.  Recorded Revision numbers are correct as well.

          Does anyone know of another, more reliable way, to get the Branch built? Hard to believe with how long Git has been around in Jenkins that this is still an issue.

          Jon Starbird added a comment - For us, the job will build the correct branch and if you look at the Environment Variables after the build the GIT_BRANCH variable is set to the correct value but if you use the GIT_BRANCH variable for Email for example the value is wrong.  Recorded Revision numbers are correct as well. Does anyone know of another, more reliable way, to get the Branch built? Hard to believe with how long Git has been around in Jenkins that this is still an issue.

          Mark Waite added a comment -

          jstarbird you could use a multi-branch pipeline with a Jenkinsfile in the root directory of each branch, then let it create a job for each branch.  When a change arrives on a branch, it is built, with the settings for that branch.  That has the added benefit of placing the job definition into source code instead of capturing the job definition as Jenkins job definition.

          Mark Waite added a comment - jstarbird you could use a multi-branch pipeline with a Jenkinsfile in the root directory of each branch, then let it create a job for each branch.  When a change arrives on a branch, it is built, with the settings for that branch.  That has the added benefit of placing the job definition into source code instead of capturing the job definition as Jenkins job definition.

          Jon Starbird added a comment -

          markewaite I'm new to Git so I'm not to sure how to work that out for the GitFlow setup we're using and building feature branches. But I'll look into that. Thanks.

          Jon Starbird added a comment - markewaite  I'm new to Git so I'm not to sure how to work that out for the GitFlow setup we're using and building feature branches. But I'll look into that. Thanks.

          Jeff Chong added a comment -

          using git version 4.0.0, this problem is still there.

          I guess you cannot trust GIT_BRANCH variable.

          Jeff Chong added a comment - using git version 4.0.0, this problem is still there. I guess you cannot trust GIT_BRANCH variable.

          Gene added a comment -

          2023 and the issue is still here. In my case, a multibranch pipeline checks out a branch. If the branch has some new commits, the GIT_BRANCH is the actual branch name. But if the branch points to the same commit as `origin/master`, then GIT_BRANCH is "master".

          Here's the offending code: https://github.com/jenkinsci/git-plugin/blob/20feaecbb9b2a1271aa7058f632e677cfb981754/src/main/java/hudson/plugins/git/GitSCM.java#L1334

          Indeed, it just blindly picks the first of the branches that contain the commit.

          Gene added a comment - 2023 and the issue is still here. In my case, a multibranch pipeline checks out a branch. If the branch has some new commits, the GIT_BRANCH is the actual branch name. But if the branch points to the same commit as `origin/master`, then GIT_BRANCH is "master". Here's the offending code: https://github.com/jenkinsci/git-plugin/blob/20feaecbb9b2a1271aa7058f632e677cfb981754/src/main/java/hudson/plugins/git/GitSCM.java#L1334 Indeed, it just blindly picks the first of the branches that contain the commit.

            Unassigned Unassigned
            sleonovich Sergey Leonovich
            Votes:
            14 Vote for this issue
            Watchers:
            21 Start watching this issue

              Created:
              Updated: