@cleyrop-org/semantic-release-backmerge

中文文档
6.2.0发布于 2026/07/31MITTypeScriptES Module近 30 天下载 4.9万

semantic-release plugin to back-merge releases into development branches. Fork of @saithodev/semantic-release-backmerge by Mario Lubenka, maintained by Cleyrop Organization.

原始使用文档
文档目录37 节
  1. What is this plugin?
  2. When to use this plugin
  3. Important Note
  4. Installation
  5. Usage
  6. Basic Configuration
  7. Cascading Backmerge Configuration
  8. Advanced Configuration with Plugins
  9. CI/CD Platform Examples
  10. Configuration Options
  11. Core Options
  12. Workspace Options
  13. Merge Strategy Options
  14. Plugin Options
  15. Performance Options
  16. Option Details
  17. backmergeBranches
  18. backmergeStrategy
  19. plugins
  20. message
  21. forcePush
  22. clearWorkspace
  23. restoreWorkspace
  24. ignorePaths
  25. mergeMode
  26. fastForwardMode
  27. fetchDelay
  28. Protected Branches
  29. Troubleshooting
  30. Merge Conflicts
  31. Stale Workspace Issues
  32. CI/CD Pipeline Loops
  33. Cascading Backmerge Issues
  34. Contributing
  35. License
  36. Acknowledgments
  37. Links

@cleyrop-org/semantic-release-backmerge

Originally created by Mario Lubenka (@saithodev) Maintained and enhanced by Jean Humann for Cleyrop Organization

semantic-release plugin to back-merge releases into development branches in your Git repository.

semantic-release Commitizen friendly Gitlab Code Coverage NPM Version NPM Downloads

What is this plugin?

This plugin enables automated back-merging from production/release branches (e.g., main/master) to development branches (e.g., develop/next) as part of your semantic-release workflow. This is particularly useful for teams using Git Flow or similar branching strategies.

When to use this plugin

  • You maintain separate production and development branches
  • You want to automatically sync releases back to your development branch
  • You use semantic-release for automated versioning and releases
  • You need to maintain development branch consistency after releases

Important Note

semantic-release in its core is not designed for Git Flow workflows with stable and unstable branches. This plugin enables such workflows, but does not guarantee seamless operation in all scenarios.

⚠️ Hotfix releases may cause merge conflicts with the development branch that require manual resolution. In such cases, the release workflow will fail, causing CI/CD pipeline failures.

StepDescription
verifyConditionsVerify access to the remote Git repository and validate the backmergeBranches configuration.
doneCreate a back-merge into the configured branch(es) if the release is successful.

Installation

npm install @cleyrop-org/semantic-release-backmerge --save-dev

Usage

Configure the plugin in your semantic-release configuration file:

Important: This plugin rebases or merges your development branch with your production branch. Ensure you have no unstaged files in your workspace, or use the clearWorkspace option to stash them temporarily.

Basic Configuration

{
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    [
      "@cleyrop-org/semantic-release-backmerge",
      {
        "backmergeBranches": ["develop"],
        "backmergeStrategy": "rebase"
      }
    ]
  ]
}

Cascading Backmerge Configuration

Create multi-level backmerge chains (e.g., main → staging → develop):

{
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    [
      "@cleyrop-org/semantic-release-backmerge",
      {
        "backmergeBranches": [
          { "from": "main", "to": "staging" },
          { "from": "staging", "to": "develop" }
        ],
        "backmergeStrategy": "merge"
      }
    ]
  ]
}

When a release is made from main, this configuration will:

  1. Backmerge main → staging
  2. Backmerge staging → develop (cascading from previous step)

Advanced Configuration with Plugins

You can run additional plugins during the backmerge to modify files for your development branch:

{
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    [
      "@cleyrop-org/semantic-release-backmerge",
      {
        "backmergeBranches": ["develop"],
        "plugins": [
          [
            "@semantic-release/exec",
            {
              "successCmd": "echo 'Version in main is ${nextRelease.version}' > VERSION.txt && git add VERSION.txt"
            }
          ]
        ]
      }
    ]
  ]
}

CI/CD Platform Examples

GitLab CI

release:
  stage: release
  image: node:24
  script:
    - npm ci
    - npx semantic-release
  only:
    - main

GitHub Actions

- uses: actions/checkout@v4
  with:
    fetch-depth: 0
    persist-credentials: false # Required for backmerging into protected branches

- name: Setup Node.js
  uses: actions/setup-node@v4
  with:
    node-version: "24"

- name: Install dependencies
  run: npm ci

- name: Release
  env:
    GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} # Use PAT with repo scope
  run: npx semantic-release

Note for GitHub Actions: To backmerge into protected branches, you need:

  1. Disable persist-credentials in the checkout action
  2. Use a Personal Access Token with repo scope in GITHUB_TOKEN
  3. Ensure the token owner has admin/maintainer access to the repository

Jenkins

withCredentials([usernamePassword(credentialsId: JENKINS_GIT_CREDENTIALS_ID,
                                  passwordVariable: 'GIT_PASSWORD',
                                  usernameVariable: 'GIT_USERNAME')]) {
    sh("git config credential.username ${GIT_USERNAME}")
    sh("git config credential.helper '!f() { echo password=$GIT_PASSWORD; }; f'")
}
withCredentials([usernameColonPassword(credentialsId: JENKINS_GIT_CREDENTIALS_ID,
                                        variable: 'GIT_CREDENTIALS')]) {
    nodejs(JENKINS_NODE_JS_INSTALLATION_LABEL) {
        sh("npx semantic-release")
    }
}

Configuration Options

Core Options

OptionDescriptionDefault
backmergeBranchesBranch names or source/target routes to receive the back-merge. See details.['develop']
backmergeStrategyHow to perform the backmerge: rebase or merge. See details.rebase
messageCommit message for back-merge (if files changed). See details.chore(release): Preparations for next release [skip ci]
forcePushForce-push the back-merge. See details.false
allowSameBranchMergeAllow back-merging into the same branch as release source.false
ignorePathsGlobal paths kept at every target branch's state. Can be overridden per route. See details.[]

Workspace Options

OptionDescriptionDefault
clearWorkspaceStash uncommitted changes before backmerge. See details.false
restoreWorkspaceRestore stashed changes after backmerge. See details.false

Merge Strategy Options

OptionDescriptionDefault
mergeModeConflict resolution when using merge strategy. See details.none
fastForwardModeFast-forward option when using merge strategy. See details.none

Plugin Options

OptionDescriptionDefault
pluginsAdditional plugins to run during backmerge. See details.[]

Performance Options

OptionDescriptionDefault
fetchDelayDelay (in ms) after fetch to allow remote git provider to sync. See details.3000

Option Details

backmergeBranches

Specify which branches should receive the back-merge. Accepts:

  • String array: Simple branch names
  • Object array: Conditional or cascading backmerges with {from: "source", to: "target"} format. An object can also define ignorePaths for that route only.

Examples

Simple backmerge to develop:

{
  "backmergeBranches": ["develop"]
}

Multiple branches:

{
  "backmergeBranches": ["develop", "next"]
}

Conditional backmerges:

{
  "backmergeBranches": [
    "develop",
    { "from": "main", "to": "staging" },
    { "from": "next", "to": "beta" }
  ]
}

In the conditional example:

  • All releases back-merge to develop
  • Releases from main also back-merge to staging
  • Releases from next also back-merge to beta

Cascading backmerges:

{
  "backmergeBranches": [
    { "from": "main", "to": "staging" },
    { "from": "staging", "to": "develop" }
  ]
}

In the cascading example, when a release is made from main:

  1. First, main is backmerged into staging
  2. Then, staging is backmerged into develop

This creates a cascade: main → staging → develop

How cascading works:

The plugin tracks which branches have been backmerged to during the current release workflow. When it encounters a {from: X, to: Y} configuration:

  • Conditional backmerge: If from equals the release branch OR has not been backmerged to yet, it only proceeds if the release originated from that branch
  • Cascading backmerge: If from is a branch that was already a to target in a previous backmerge, it will merge from that branch regardless of the release origin

This allows you to create multi-level backmerge chains while maintaining backward compatibility with existing configurations.

Mixed configuration example:

{
  "backmergeBranches": [
    "hotfix",
    { "from": "main", "to": "staging" },
    { "from": "staging", "to": "develop" }
  ]
}

When a release is made from main:

  • main → hotfix (simple backmerge)
  • main → staging (conditional backmerge)
  • staging → develop (cascading backmerge)

Template Variables

You can use Lodash template syntax in branch names:

{
  "backmergeBranches": ["${branch.name}-develop"]
}

Available variables:

VariableDescription
branchThe release branch object
branch.nameBranch name
branch.typeBranch type (release/prerelease/maintenance)
branch.channelDistribution channel
branch.rangeSemantic version range
branch.prereleasePrerelease identifier

backmergeStrategy

Determines how the development branch receives changes from the production branch.

Options:

  • rebase (default): Replays development branch commits on top of production
  • merge: Creates a merge commit from production into development

Example:

{
  "backmergeStrategy": "merge"
}

plugins

Run additional semantic-release plugins during the backmerge phase. Useful for modifying files for the development branch (e.g., updating version files, adding dev suffixes).

Important: Plugins must stage their changes to Git (git add) for inclusion in the back-merge commit.

Example:

{
  "plugins": [
    [
      "@semantic-release/exec",
      {
        "successCmd": "npm version ${nextRelease.version}-dev --no-git-tag-version && git add package.json"
      }
    ]
  ]
}

message

Customize the commit message for back-merge commits using Lodash template syntax.

Available variables:

VariableDescription
branchRelease branch object (see structure above)
lastReleasePrevious release (version, gitTag, gitHead)
nextReleaseCurrent release (version, gitTag, gitHead, notes)

Example:

{
  "message": "chore: merge v${nextRelease.version} into develop [skip ci]"
}

Tip: Include [skip ci] to prevent triggering another CI build.

forcePush

Force-push the back-merge to the development branch.

⚠️ Warning: This will overwrite commits in the development branch that aren't in production. Use with extreme caution!

{
  "forcePush": true
}

clearWorkspace

Stash uncommitted changes before attempting the backmerge.

{
  "clearWorkspace": true
}

restoreWorkspace

Restore stashed changes after the backmerge completes. Only meaningful with clearWorkspace: true.

{
  "clearWorkspace": true,
  "restoreWorkspace": true
}

ignorePaths

A list of paths to exclude from a back-merge. After the merge/rebase, each listed path is restored to the target branch's pre-back-merge state, so any changes to it on the source branch are never carried over. Works with both the merge and rebase strategies.

This is useful for files that must diverge per branch and would otherwise be clobbered by the back-merge — typically version pins or release matrices that hold different values on staging vs develop.

{
  "backmergeBranches": [
    { "from": "main", "to": "staging" },
    {
      "from": "staging",
      "to": "develop",
      "ignorePaths": ["version-matrix.yaml.jinja"]
    }
  ],
  "backmergeStrategy": "merge"
}

In this example, version-matrix.yaml.jinja is excluded only while back-merging staging into develop; it is still included in the main to staging back-merge.

The top-level ignorePaths option remains supported and applies to every back-merge. A route-specific ignorePaths value takes precedence for that route. Use an empty route-specific array to disable the global exclusions for one route:

{
  "ignorePaths": ["version-matrix.yaml.jinja"],
  "backmergeBranches": [
    {
      "from": "main",
      "to": "staging",
      "ignorePaths": []
    },
    { "from": "staging", "to": "develop" }
  ]
}

Behaviour:

  • Each matched file is reset whole to the target branch's version (not line-merged).
  • Files that exist on the release branch but not on the target are removed, so the result matches the target exactly.
  • Path specs (including globs, e.g. "values/**") that match nothing are skipped — they never abort the back-merge.

mergeMode

When using backmergeStrategy: "merge", determines conflict resolution strategy.

Options:

  • none (default): No automatic resolution (fails on conflicts)
  • ours: Prefer development branch changes
  • theirs: Prefer production branch changes
{
  "backmergeStrategy": "merge",
  "mergeMode": "theirs"
}

fastForwardMode

When using backmergeStrategy: "merge", controls fast-forward behavior.

Options:

  • none (default): Same as ff
  • ff: Fast-forward when possible, merge commit otherwise
  • no-ff: Always create a merge commit
  • ff-only: Only fast-forward, fail if not possible
{
  "backmergeStrategy": "merge",
  "fastForwardMode": "no-ff"
}

fetchDelay

Delay (in milliseconds) after pushing to the remote repository before fetching to update local branch references. This allows remote git providers (GitHub, GitLab, Bitbucket) additional time to fully process and synchronize the push operation.

Why you might need this:

  • Remote git providers may have a small delay between when a push completes and when those changes are available for subsequent fetch operations
  • This is critical for cascading backmerges where one backmerge's push must be fully visible to the remote before the next backmerge fetches
  • Network latency, CDN propagation, and API processing can cause timing issues
  • Without this delay, cascading backmerges may not include all expected commits

Default: 3000 (3 seconds)

Examples:

Disable delay for local repositories or faster CI:

{
  "fetchDelay": 0
}

Increase delay for slower networks or remote providers:

{
  "fetchDelay": 5000
}

Note: The default 3-second delay provides a reasonable buffer for most remote git providers. Only adjust if you experience timing-related failures or want to optimize CI speed for local repositories.

Protected Branches

To backmerge into protected branches:

  1. Use credentials with admin/maintainer permissions
  2. Provide appropriate access token (e.g., GITHUB_TOKEN, GITLAB_TOKEN)
  3. For GitHub Actions, disable persist-credentials in checkout action

Troubleshooting

Merge Conflicts

If automated backmerge fails due to conflicts:

  1. Manually resolve conflicts in your development branch
  2. The next release will attempt backmerge again

Stale Workspace Issues

If you encounter "unstaged changes" errors:

  • Set clearWorkspace: true to automatically stash changes
  • Set restoreWorkspace: true if you need those changes restored

CI/CD Pipeline Loops

Ensure your commit message includes [skip ci] or equivalent to prevent infinite release loops.

Cascading Backmerge Issues

If cascading backmerges (e.g., main → staging → develop) are not including all expected commits:

Symptoms:

  • Commits from the first branch (e.g., main) don't appear in the final branch (e.g., develop)
  • Merge messages reference the correct branch but history is incomplete
  • Integration tests show missing commits in cascade chains

Solutions:

  1. Increase fetchDelay: The default 3-second delay may not be sufficient for some remote providers

    {
      "fetchDelay": 5000
    }
    
  2. For local testing: Set fetchDelay: 0 since local git repositories don't have synchronization delays

    {
      "fetchDelay": 0
    }
    
  3. Check remote configuration: Ensure your git remote is properly configured as origin

    git remote -v
    

Technical Note: The plugin uses git fetch origin to update remote-tracking branches. If your remote has a different name, you may need to adjust your git configuration or create an origin alias.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT License - see the LICENSE file for details

Acknowledgments

This project is a fork and continuation of the original @saithodev/semantic-release-backmerge created by Mario Lubenka. We're grateful for the foundational work and maintain this fork to provide continued support and enhancements.

版本与发布记录

@cleyrop-org/semantic-release-backmerge 共发布 12 个版本,首次发布于 2025/10/19;过去 12 个月发布了 3 个版本。

版本发布日期距今
6.2.0latest2026/07/313 个月前
6.1.02026/06/254 个月前
6.0.02026/06/104 个月前
5.2.42025/10/211.1 年前
5.2.32025/10/201.1 年前
5.2.22025/10/201.1 年前

关于 @cleyrop-org/semantic-release-backmerge 的常见问题

@cleyrop-org/semantic-release-backmerge 是什么?

semantic-release plugin to back-merge releases into development branches. Fork of @saithodev/semantic-release-backmerge by Mario Lubenka, maintained by Cleyrop Organization.

如何安装 @cleyrop-org/semantic-release-backmerge?

在项目目录运行 npm install @cleyrop-org/semantic-release-backmerge,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:semantic-release(>=24)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@cleyrop-org/semantic-release-backmerge 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cleyrop-org/semantic-release-backmerge 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@cleyrop-org/semantic-release-backmerge 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js ^22.14.0 || >=24.10.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@cleyrop-org/semantic-release-backmerge 可以商用吗?

@cleyrop-org/semantic-release-backmerge 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@cleyrop-org/semantic-release-backmerge 的下载量有多少?

根据 npm 官方下载统计,@cleyrop-org/semantic-release-backmerge 在 2026/10/10 – 2026/11/08 这 30 天内被下载 49,034 次,日均约 1,634 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cleyrop-org/semantic-release-backmerge 还在维护吗?

最新版本 6.2.0 发布于 2026/07/31(3 个月前);至今共发布 12 个版本,其中过去 12 个月发布了 3 个;首次发布于 2025/10/19。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。