Jenkins流水线无法识别Git分支导致分支对比命令执行失败
问题根因
Jenkins流水线默认的Git拉取逻辑做了性能优化,存在三个直接导致报错的问题:
- 默认开启浅克隆,仅拉取当前触发流水线的单次提交记录,不会拉取完整提交历史,也不会拉取除当前分支外的其他分支内容
- 默认仅拉取当前触发分支的引用,PR场景下的
${env.CHANGE_TARGET}(合入目标分支)、${env.CHANGE_BRANCH}(PR发起分支)的远程引用都不会被拉到本地工作区 stash步骤默认仅暂存工作区的源码文件,不会暂存.git目录下的分支引用、提交记录等Git元数据,如果是跨节点unstash后执行Git命令,工作区本身就不具备完整Git仓库结构,自然找不到对应分支。
当前暂存阶段的执行输出如下:
执行diff命令的报错输出如下:
修复方案
按以下步骤调整配置即可解决:
- 调整代码拉取(checkout)阶段配置,关闭浅克隆,配置拉取全部分支引用,参考配置如下:
stage('Checkout') { steps { checkout([ $class: 'GitSCM', branches: [[name: '*/*']], extensions: [ // 关闭浅克隆,拉取完整提交历史 [$class: 'CloneOption', shallow: false, depth: 0, noTags: false], // 配置拉取所有远程分支的引用 [$class: 'FetchOption', refspec: '+refs/heads/*:refs/remotes/origin/*'] ], // 替换为实际的仓库地址和凭证ID userRemoteConfigs: [[credentialsId: 'your-git-credential-id', url: 'your-git-repo-url']] ]) } }
- 执行diff命令前,先显式拉取两个对比分支的最新提交,同时注意给分支名加上
origin/远程前缀,修正后的命令如下:
stage('Get changed dirs') { steps { script { // 先拉取两个对比分支的最新提交 sh 'git fetch origin ${env.CHANGE_BRANCH} ${env.CHANGE_TARGET}' // 执行diff时指定远程分支路径,输出结果可直接赋值给变量复用 def changedDirs = sh( script: 'git diff --name-only -r origin/${env.CHANGE_BRANCH} origin/${env.CHANGE_TARGET} | xargs -L1 dirname | uniq | awk \'{print "./"$0}\'', returnStdout: true ).trim() } } }
- 不推荐跨节点
unstash源码后执行Git相关命令:stash传递.git目录效率极低,容易出现引用损坏,如果需要在其他节点执行Git操作,直接在对应节点重新执行带完整配置的checkout步骤即可。
内容的提问来源于stack exchange,提问作者DISCO
相关产品推荐
相关产品推荐

