Gradle-release-plugin更新被拒绝,因为当前分支的尖端在后面

时间:2020-05-06 01:47:34

标签: git gradle build.gradle gradle-plugin gradle-release-plugin

在我的工作场所,我们使用每月发布的分支,该分支在多个开发人员之间共享。

Gradle版本为2.14.1

我们使用Jenkins(有效运行-gradle clean compileJava版本)手动触发代码的构建和发布(任务)

整个过程大约需要30-40分钟,基本上是编译,生成工件,运行Junit测试并将工件上传到Artifactory。

最终涉及标记和推送版本号的步骤: preTagCommit ,它尝试更新gradle.properties并提高版本号,然后提交和推送。

这时,如果在过去30-40分钟内分支上没有任何提交(自从手动触发了构建以来),则该发行版将成功工作。

在整个过程之间甚至只有一次提交时,它就会因错误而失败: 任务':preTagCommit'的执行失败。

*
error: failed to push some refs to 'xxx.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
*

我尝试了几次黑客攻击并搜索了文档,但尚未找到合适的解决方案。

这是我的发布步骤的样子:

***
    release {
        project.setProperty("gradle.release.useAutomaticVersion", "true");
        newVersionCommitMessage = "Re-snapshoted project to version "
        preTagCommitMessage = "Preparing version for release "
        tagCommitMessage = "Tagging Release "
        tagPrefix = "calypso"
        requireBranch = ""
        // Sometimes the plugin trips over its own feet with modifying the gradle.properties
        // then complaining it has changed.
        failOnCommitNeeded = false
        pushToCurrentBranch = true
    }
***

很抱歉,如果以前曾问过这个问题,我发现的所有解决方案都是通用的git方法,而不是使用git的Gradle-Release-Plugin的人。

任何回复将不胜感激。

2 个答案:

答案 0 :(得分:1)

我相信插件的GitHub page中提到了您要查找的标志:

例如。要忽略上游更改,请将'failOnUpdateNeeded'更改为false:

release {
  failOnUpdateNeeded = false
}

编辑

上面的标志似乎由于某种原因不起作用。但是,还有另一种方法可以完成此操作,即在release扩展名的git选项中添加一个强制推送选项(实话实说)。

release {
  git {
    pushOptions = ['--force']
  }
}

这将基本上强制覆盖分支(请参阅下面的问题分析),除非已将托管存储库的服务器调整为拒绝此类强制推送。在这种情况下,实际上没有可以通过的选项。


问题分析

正如我在下面的最后一条评论中所述,失败的部分是扩展运行preTagCommit任务,然后尝试将此提交推送到上游分支(例如master)。您可以在here右边看到此推送命令。

当然,如果其他人已经将提交推送到该分支,这将失败。

现在,解决此问题的一种更简单的方法是,如果插件作者允许我们说

不要将preTag提交到上游

将preTagCommits推送到名为foo的分支

不幸的是,他们没有给我们这个选项(到目前为止,我收集的信息还不多)。因此,我想出了一些解决方案来解决此问题。

解决方案/问题

指定pushToBranchPrefix 创建带标签的分支

这是另一个option,可以传递给git对象,这导致将所有操作确实推送到具有给定前缀而不是当前分支的特定分支: / s>

例如:

afterReleaseBuild {
  doFirst {
    project.exec {
        executable = 'git'
        args 'checkout', '-b', 'v1.x.x@master'
    }
  }
}

用与当前版本的标签匹配的内容替换v1.x.x

这是什么意思,每当插件尝试推送/提交时,它都会将推送/提交到我们创建的这个分支,最后也从该分支创建标签。

我认为这可能是最好的选择

禁用preTagCommit任务

由于preTagCommit任务失败了,因此我们可以禁用该任务,它将不再运行:

tasks.named('preTagCommit') {
    enabled = false
}

自己确定是否可以接受。

动态推送行为

因为我看过源代码,所以我可以see看到它的原因是git.pushToRemote不为空。知道了这一点,我们就可以动态地控制这种行为。

tasks.named('preTagCommit') {
  def pushToRemote = null
  doFirst {
    project.extensions.configure(net.researchgate.release.ReleaseExtension) {
      pushToRemote = it.git.pushToRemote
      it.git.pushToRemote = null
    }
  }

  doLast {
    project.extensions.configure(net.researchgate.release.ReleaseExtension) {
      it.git.pushToRemote = pushToRemote
    }
  }
}

这样,在preTagCommit中,它不会执行任何操作,但会在其他所有操作上成功。

答案 1 :(得分:0)

对于我来说,最简单的方法是在build.gradle中为我的发布插件组件进行修改:

***
release {
....
 pushToRemote = ''
....
}
***

这可确保发布插件不会推送!

从gradle版本获得控制权之后,我进行了后续操作:

Git拉出点

Git push-标记起源

这很好地同步了我的提交,并且遵循了“推入前推”规则!

尽管这是一个棘手的解决方案,但@Clijsters建议我使用Special release分支来解决此问题。