Jenkins Git 插件分离 HEAD
Posted
技术标签:
【中文标题】Jenkins Git 插件分离 HEAD【英文标题】:Jenkins Git plugin detached HEAD 【发布时间】:2012-07-15 17:14:57 【问题描述】:我是 Git 的新手,也是 Jenkins 的新手。我的问题是我无法让 Jenkins Maven 发布插件工作。
当我使用 Jenkins 构建通用 Maven 构建时,它运行良好,但是当我尝试使用 Maven 发布插件执行发布时,我得到以下堆栈跟踪:
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.3.2:prepare (default-cli) on project parent: An error is occurred in the checkin process: Exception while executing SCM command.
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:217)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.jvnet.hudson.maven3.launcher.Maven3Launcher.main(Maven3Launcher.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchStandard(Launcher.java:329)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:239)
at org.jvnet.hudson.maven3.agent.Maven3Main.launch(Maven3Main.java:158)
at hudson.maven.Maven3Builder.call(Maven3Builder.java:98)
at hudson.maven.Maven3Builder.call(Maven3Builder.java:64)
at hudson.remoting.UserRequest.perform(UserRequest.java:118)
at hudson.remoting.UserRequest.perform(UserRequest.java:48)
at hudson.remoting.Request$2.run(Request.java:326)
at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.apache.maven.plugin.MojoExecutionException: An error is occurred in the checkin process: Exception while executing SCM command.
at org.apache.maven.plugins.release.PrepareReleaseMojo.prepareRelease(PrepareReleaseMojo.java:295)
at org.apache.maven.plugins.release.PrepareReleaseMojo.execute(PrepareReleaseMojo.java:247)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
... 27 more
Caused by: org.apache.maven.shared.release.ReleaseExecutionException: An error is occurred in the checkin process: Exception while executing SCM command.
at org.apache.maven.shared.release.phase.AbstractScmCommitPhase.checkin(AbstractScmCommitPhase.java:160)
at org.apache.maven.shared.release.phase.AbstractScmCommitPhase.performCheckins(AbstractScmCommitPhase.java:145)
at org.apache.maven.shared.release.phase.ScmCommitPreparationPhase.runLogic(ScmCommitPreparationPhase.java:76)
at org.apache.maven.shared.release.phase.AbstractScmCommitPhase.execute(AbstractScmCommitPhase.java:78)
at org.apache.maven.shared.release.DefaultReleaseManager.prepare(DefaultReleaseManager.java:234)
at org.apache.maven.shared.release.DefaultReleaseManager.prepare(DefaultReleaseManager.java:169)
at org.apache.maven.shared.release.DefaultReleaseManager.prepare(DefaultReleaseManager.java:146)
at org.apache.maven.shared.release.DefaultReleaseManager.prepare(DefaultReleaseManager.java:107)
at org.apache.maven.plugins.release.PrepareReleaseMojo.prepareRelease(PrepareReleaseMojo.java:291)
... 30 more
Caused by: org.apache.maven.scm.ScmException: Exception while executing SCM command.
at org.apache.maven.scm.command.AbstractCommand.execute(AbstractCommand.java:63)
at org.apache.maven.scm.provider.git.AbstractGitScmProvider.executeCommand(AbstractGitScmProvider.java:291)
at org.apache.maven.scm.provider.git.AbstractGitScmProvider.checkin(AbstractGitScmProvider.java:217)
at org.apache.maven.scm.provider.AbstractScmProvider.checkIn(AbstractScmProvider.java:410)
at org.apache.maven.shared.release.phase.AbstractScmCommitPhase.checkin(AbstractScmCommitPhase.java:156)
... 38 more
Caused by: org.apache.maven.scm.ScmException: Detecting the current branch failed: fatal: ref HEAD is not a symbolic ref
at org.apache.maven.scm.provider.git.gitexe.command.branch.GitBranchCommand.getCurrentBranch(GitBranchCommand.java:147)
at org.apache.maven.scm.provider.git.gitexe.command.checkin.GitCheckInCommand.createPushCommandLine(GitCheckInCommand.java:192)
at org.apache.maven.scm.provider.git.gitexe.command.checkin.GitCheckInCommand.executeCheckInCommand(GitCheckInCommand.java:132)
at org.apache.maven.scm.command.checkin.AbstractCheckInCommand.executeCommand(AbstractCheckInCommand.java:54)
at org.apache.maven.scm.command.AbstractCommand.execute(AbstractCommand.java:59)
... 42 more
channel stopped
Finished: FAILURE
失败的命令和错误信息是:
[INFO] Executing: /bin/sh -c cd
/var/lib/jenkins/workspace/test_maven/parent && git symbolic-ref HEAD
[INFO] Working directory:
/var/lib/jenkins/workspace/test_maven/parent mojoFailed
org.apache.maven.plugins:maven-release-plugin:2.3.2(default-cli)
projectFailed ch.apkern.achilles:parent:1.0-SNAPSHOT sessionEnded
我认为 Jenkins Git 插件创建了一个分离的 HEAD ref“(无分支)”,这会导致问题。但我完全不知道为什么要创建这个 ref 或者我如何解决这个问题。
如果有任何帮助,我将不胜感激。
【问题讨论】:
您的问题解决了吗?如果是这样,如果您能接受答案,如果它有帮助或提供您自己的答案,这样其他人可以从知识中受益,那就太好了,谢谢! Active Git branch is "(no branch)" on hudson CI的可能重复 【参考方案1】:在 Git 中,当您签出一个分支时,例如 master 或 dev 或任何其他本地分支,您的 HEAD(.git 文件夹中的文件)将包含对相应分支的引用。因此它是“附加的”。
当你执行一些操作比如变基、合并或者当你检查一个特定的提交时,即当你看到“没有分支”时,你的 HEAD 没有对任何本地分支的引用,而是直接指向提交,即它里面有实际的SHA-1。这意味着它是分离的 - 与任何分支分离。 没有创建新的引用“无分支”。
git symbolic-ref HEAD
命令检查 HEAD 内容是引用还是 SHA-1 并将其打印出来。
您可以这样做:
git checkout master
git symbolic-ref HEAD
git checkout HEAD~2 # going two commits back
git symbolic-ref HEAD
git checkout master # coming back
现在,Jenkins 中的 Git 插件大部分时间都在分离 HEAD 状态下处理代码。我不确定 Maven 发布插件是如何工作的,但我 99% 确定它需要您从特定分支发布。为了解决这个问题,我建议指定如下内容作为预构建步骤或 shell 命令:
git checkout master; git pull origin master
希望能解决问题;)
【讨论】:
感谢您的帮助!我已经找到了再次签出主分支的这种方式。但是 maven 发布插件也使用 git 插件来获取源,这意味着 maven 发布插件只调用带有参数的发布目标。在这到两个步骤之间无法调用预构建步骤。 好吧,据我了解,发布目标是您应该能够调整的。您知道它无法确定当前分支,因此您应该能够调整发布目标准备,以便它能够在正确的分支中签出项目。我认为最好的方法是定义你总是从中释放的单个分支,比如 master,并通过显式检查 master 分支来改变你的“准备”目标以适应插件。【参考方案2】:更新(2015 年 11 月):请注意,此解决方案是针对特定版本的 Git 插件 (1.1.26) 提供的。在以后的版本中,插件进行了更新,使配置更容易。
对于 Jenkins Git 插件版本 1.1.26,试试这个:
转到作业配置。向下滚动到 Git 部分,然后单击“存储库”下的“高级...”按钮。然后设置:
Name: origin
Refspec: +refs/heads/branch-0.1:refs/remotes/origin/localbranchname
然后点击另一个“高级...”按钮并设置:
Checkout/merge to local branch (optional): localbranchname
您可以随意命名本地分支,但 Refspec 中的目标必须与该可选字段中的本地分支名称匹配(在本例中为“localbranchname”)。这会将 HEAD 附加到 localbranchname,如下所示:
HEAD -> refs/heads/localbranchname -> 7a698457751bdc043cfda631b81e3812c5361790
Maven Release 现在应该在 Jenkins 中通过。
顺便说一句,这适用于 Jenkins 1.492 和 Jenkins Git 插件版本 1.1.26。
【讨论】:
本地分支(可选)设置是我唯一需要的设置 和我一样。 (可选)设置产生了足够的差异。另外,我正在使用 CloudBees 并在 GitHub 上注册了一个 SSH 密钥。向 Maven 发布插件提供用户名/密码会导致问题。我终于在没有用户名/密码的情况下成功发布,让SSH接管。 顺便说一句,从 Jenkins 1.547 开始(至少我正在运行),第二个高级按钮消失了。您可以通过在“其他行为”下选择其他行为来签出特定的本地分支。 我能够在 Jenkins 1.627 中通过将“其他行为”下的“签出到特定本地分支”字段设置为“主”来解决此问题。 它部分工作,我的仓库现在在我想要的分支上,但是当我尝试推送时,我得到了fatal: The current branch master has no upstream branch
。我在 Jenkins Git 配置中尝试了不同的参数,但没有运气,我只是不想在推送中硬编码分支名称,如 git push -u origin master
【参考方案3】:
我遇到了同样的问题。 @Eugene 解决方案只工作了一次。
第二次尝试出现错误:“无法从存储库中删除 HEAD”或类似的内容。
我找到了这个 (source):
和 m2 额外步骤(预构建)
git checkout master || git checkout -b master
git reset --hard origin/master
现在我觉得还可以。
【讨论】:
【参考方案4】:我遇到了同样的问题。 我尝试了康斯坦丁的解决方案,效果很好,但标签和提交被推送到“localbranchname”远程存储库。
所以我做了同样的事情,但是是手动的。
首先,添加一个 pre-steps shell 脚本:
git branch -f localJenkins
git checkout localJenkins
然后是一个 post-steps shell 脚本:
git checkout master
git rebase localJenkins
git branch -D localJenkins
git push origin master
git push --tag
这行得通! 这样,您就没有 jenkins 远程分支,提交和标记将在主(或其他)分支上。
【讨论】:
【参考方案5】:无需创建手动步骤,其他答案的 Jenkins 配置均不适合我。真正有效的方法很简单:
Repository URL: <repo>
Branches to build: master
Checkout/merge to local branch (optional): master
【讨论】:
【参考方案6】:Checkout/merge to local branch (optional) 字段在 Git 插件的当前 (2.2.1) 版本中消失了。
它已移至其他行为 → 查看特定的本地分支:
将该值设置为 master 让我得到了一个签出的分支,而不是一个分离的头。
【讨论】:
如果你想构建多个分支,在 GIT 插件 2.4.0(可能更早?)中,你可以设置本地分支名称$GIT_BRANCH
,并得到一个以远程分支命名的分支。 (刚刚用该信息发布了我自己的答案。)
只想添加将值设置为“**”或将其留空是更好的选择。将计算本地分支名称。起源/测试 -> 测试
@AndreyKlochkov 它确实按照你说的做,但问题是它使用提交 sha 作为起点,例如git checkout -b develop 1694bf...
-- 这可以防止分支拥有上游远程设置,这意味着您需要在事后执行手动 shell 脚本来设置它
对我来说,“*”导致了一个错误,但将其留空按预期工作
@lewis:我认为应该是两个星号,而不是一个。【参考方案7】:
我想建立几个分支,并在其名称下检查每个分支。我正在使用 Git 插件 2.4.0。
answer by Matthias Braun 为您提供了一个命名分支,但它不是以远程分支命名的。
不要将本地分支设置为master
,将本地分支设置为$GIT_BRANCH
。
我在this bug report 中找到了该解决方案。
【讨论】:
将本地分支设置为 $GIT_BRANCH 为我在远程创建了一个新分支:origin/origin/master。将参数留空似乎可以正常工作。【参考方案8】:为发布准备添加到maven命令行:-DpushChanges=false -DlocalCheckout=true
这意味着 maven 将使用 jenkins 在工作目录 .git
中获得的内容,并且既不会克隆远程也不会推送到远程。
我建议将完全限定的 refs/remotes/origin/develop
配置为您的 Git “要构建的分支”。这种方式对我来说似乎更容易理解。
在这种情况下,您的 $GIT_BRANCH 会被 Jenkins 神奇地设置为 origin/develop
然后,不要使用过于复杂(但可移植的)GitPublisher,只需添加一个构建后步骤“Execute Shell”:
echo Remote branch is $GIT_BRANCH, replacing origin with refs/heads.
git push --follow-tags "$GIT_URL" "+HEAD:$GIT_BRANCH/#origin\//refs/heads/"
这会推送 maven 更改的任何内容,例如 pom.xml 和标签。
【讨论】:
【参考方案9】:我在尝试使用 maven-release-plugin:2.5.3 和 maven-scm-provider-jgit:1.9.5 从分支进行参数化发布构建时遇到了同样的问题。
我希望能够为“参数化发布构建”选择分支。这不起作用,当我选择“结帐/合并到本地分支(可选)”时它起作用了,但我最终在远程(重复来源)中得到了一个分支“origin/origin/mybranch”。
所以:
将“Git 参数”添加到“此项目已参数化” 名称:分公司 参数类型:分支 点击高级: 分支过滤器:origin/(.*) (这就是诀窍!)
Git 存储库: 要构建的分支:refs/remotes/origin/$branch
其他行为:-> 查看特定的本地分支 分支名称:$branch
玩得开心:-)
【讨论】:
这需要安装“Git 参数”插件【参考方案10】:如果您正在使用来自 SCM 的管道脚本,以下是实现another answer 中以图形方式显示的内容所需的语法:
extensions: [[$class: 'LocalBranch', localBranch: 'BRANCH_NAME']]
因此,例如,如果您的远程分支是 develop
,并且您想签出一个也称为 develop
的本地分支来跟踪它,那么这里有一个在上下文中显示本地分支扩展的最小示例:
checkout([$class: 'GitSCM', branches: [[name: '*/develop']], extensions: [[$class: 'LocalBranch', localBranch: 'develop']], userRemoteConfigs: [[credentialsId: 'xxx', url: 'yyy']]])
xxx
和 yyy
将分别替换为您自己的凭据 ID 和 URL。
您也可以使用图形语法生成器自己生成管道语法。见this answer。
【讨论】:
以上是关于Jenkins Git 插件分离 HEAD的主要内容,如果未能解决你的问题,请参考以下文章