Jenkins Git 插件:默认用“拉所有分支”的方式
仓库配置了 dev 分支,dev/xxx 分支,导致 Jenkins 拉取故障
错误日志:
From http://10.63.32.225/ai-platform/meetings-agent
* [new branch] dev-2026-01-14 -> origin/dev-2026-01-14
error: unable to resolve reference refs/remotes/origin/dev/init: Not a directory
! [new branch] dev/init -> origin/dev/init (unable to update local ref)
error: some local refs could not be updated; try running
Jenkins 配置
checkout([$class: 'GitSCM',
branches: [[name: branch]],
doGenerateSubmoduleConfigurations: false,
extensions: [],
gitTool: 'Default',
submoduleCfg: [],
userRemoteConfigs: [[url: repositoryAddr]]
])虽然指定了 branches: [[name: branch]],比如 dev-2026-01-14,但 Jenkins Git 插件在内部是这样干的(简化理解):
设置远程
origin为你给的repositoryAddr执行类似:
git fetch --tags --progress http://.../repo.git +refs/heads/*:refs/remotes/origin/*也就是:把所有远程分支都同步到本地 remotes/origin 下
然后再
git checkout你指定的branch分支
原因主要有几个:
Jenkins 要支持很多高级场景:
构建前对比本次变更(需要知道其他分支的状态);
多分支流水线 / PR 构建(动态切各种分支);
tag 构建等。
所以它的默认策略是:
“把远端的状态都同步下来,我再在本地随意切来切去。”
这就是为什么只想用 dev-2026-01-14,但日志里还是看到在同步 dev/init——因为插件的 fetch 是“*”,把 dev/init 也包含进来了
dev/init 无法当成一个分支,要解析成 dev 下的分支,dev 就是目录,但是已经有一个 dev 分支了
能不能让 Jenkins 只拉一个分支?
理论上可以,但:
通过 Jenkins 界面配置 SCM 时,可以比较方便地定制 refspec;
在 Pipeline 里直接写
$class: 'GitSCM'这种方式,Git 插件会套用它的一套默认 refspec(就是refs/heads/*),修改起来不太直观,容易和 UI 配置冲突;而且你现在用的方式在大多数项目上都跑得很好,说明默认行为是“广泛被接受的通用配置”。
更现实的做法是:
接受“Jenkins 会拉所有分支”这个事实;
在业务上避免这种“前缀 + 带斜杠”的分支搭配(
dev与dev/xxx);对已经出问题的 workspace,手动修一次本地 refs(删除旧的
origin/dev文件),或者在构建前用deleteDir()清空 workspace,让整个 git 仓库重新初始化。