Skip to main content

Crate bump2version

Crate bump2version 

Source
Expand description

§⬆️ Bump2version

bump2version logo

Crates.io Docs.rs PyPI npm Docker GitHub Marketplace License: MIT

bump2version is the world’s fastest version bumper written entirely in 100% safe Rust, with no_std support, native Python and Node.js bindings, and a cargo bump subcommand 🗿.

bump2version banner

§🚀 Installation

PlatformCommand
Rust binarycargo install bump2version --features rust-binary
Cargo subcommandcargo bump --help
Dockerdocker pull wiseaidev/bump2version
Debian/UbuntuDownload .deb from GitHub Releases
RHEL/FedoraDownload .rpm from GitHub Releases
WindowsDownload bump.exe from GitHub Releases
GitHub ActionSee action.yml
Pythonpip install bump-rs
Node.jsnpm install bump2version

[!NOTE] Installing via cargo installs both bump and bump2version binaries. The original bump2version binary is retained indefinitely for backward compatibility with existing tutorials, CI/CD pipelines, and automation scripts.

§🤔 What does this crate provide?

bump2version automates semantic version management for any project regardless of language. It:

  • Parses version strings using a fully configurable regex (default: semver major.minor.patch).
  • Bumps any named component (major, minor, patch, or custom cyclic stages like alpha → beta → rc → stable).
  • Rewrites version occurrences across multiple files, including multiline CHANGELOG patterns.
  • Commits and tags via 100% pure gix (gitoxide); zero subprocess calls.
  • Detects version strings across any language’s manifest files (Rust, Python, JS, Go, Java, Ruby).
  • Watches for file changes and bumps automatically on save (one bump per save, with debounce).
  • Bumps workspaces atomically across all Cargo workspace members.

§💻 Command-line Interface

# Install
cargo install bump2version --features rust-binary

# Use directly
bump --bump patch          # 0.2.1 → 0.2.2
bump --bump minor          # 0.2.1 → 0.3.0
bump --bump major          # 0.2.1 → 1.0.0
bump --bump patch --dry-run  # preview only

# Use as cargo subcommand
cargo bump --bump patch
cargo bump --bump minor --dry-run

# Docker
docker run --rm -v $(pwd):/workspace wiseaidev/bump2version --bump patch --dry-run

# Multi-language auto-detect
bump --bump patch --detect
OptionDescription
--config-fileConfig file path (default: .bumpversion.toml)
--current-versionOverride current version
--bumpComponent: major, minor, patch, or any custom part
--parseParse regex override
--serializeSerialize format override
--dry-run / -nSimulate without writing files
--new-versionExplicit new version (skips bump calculation)
--commit / --tagGit commit + lightweight tag

§🔭 Features

FeatureDefaultDescription
std✅File I/O, git integration, regex stdlib cache
cli❌Standalone bump binary via clap
watch❌File-system watcher (bump on file save)
detect❌Multi-language manifest auto-detection
python❌Python extension module via PyO3/maturin
node❌Node.js native add-on via napi-rs

§🦀 Rust

The Rust crate is available on crates.io. For a complete API reference visit RUST.md.

§Quick Start

[dependencies]
bump2version = "0.2.2"
use bump2version::{config::BumpConfig, version::{BumpPart, parse_version, bump_version, serialize_version}};

fn main() {
    let cfg = BumpConfig::default();
    let v   = parse_version("1.2.3", &cfg).unwrap();
    let v2  = bump_version(&v, &BumpPart::Patch, &cfg).unwrap();
    println!("{}", serialize_version(&v2, &cfg)); // 1.2.4
}

§no_std Support

Core modules (config, version, files, error) compile in no_std + alloc:

bump2version = { version = "0.2.2", default-features = false }
Moduleno_std+allocstd
config✅✅
version✅✅
files✅✅
error✅✅
git❌✅
CLI❌✅
Python / Node.js❌✅

§🐍 Python

pip install bump-rs
from bump_rs import bump_version, apply_file_change, BumpConfig

print(bump_version("1.2.3", "patch"))   # "1.2.4"
print(bump_version("1.2.3", "minor"))   # "1.3.0"

cfg = BumpConfig(parse=r"(?P<major>\d+)\.(?P<minor>\d+)", serialize="{major}.{minor}")
print(bump_version("2.0", "minor", config=cfg))  # "2.1"

For full docs see PYTHON.md.

§🟩 Node.js

npm install bump2version
const { bumpVersion, applyFileChange } = require("bump2version");
console.log(bumpVersion("1.2.3", "patch")); // '1.2.4'

For full docs see NODE.md.

§⚙️ Configuration File (.bumpversion.toml)

[bumpversion]
current_version = "1.0.0"
commit = true
tag = true

[bumpversion:file:Cargo.toml]
search = name = "my-crate"
    version = "{current_version}"
replace = name = "my-crate"
    version = "{new_version}"

[bumpversion:file:CHANGELOG.md]
search = """
## {current_version}
    Release notes line 1"""
replace = """
## {new_version}
    Release notes line 1"""

§Pre-release Cycling

[bumpversion]
current_version = "1.0.0-alpha.1"
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)-(?P<stage>[a-z]+)\.(?P<devnum>\d+)
serialize =
    {major}.{minor}.{patch}-{stage}.{devnum}
    {major}.{minor}.{patch}

[bumpversion:part:stage]
optional_value = stable
first_value = alpha
values =
    alpha
    beta
    rc
    stable

§Cargo Workspace Bumping

# Atomically bump all workspace member crates
bump --bump patch

The workspace module discovers all [workspace] members and bumps every Cargo.toml in one pass.

§🔭 GitHub Action

The action is published as bump-rs on the GitHub Marketplace.

- name: bump-rs
  uses: wiseaidev/bump2version@v0.2.2
  with:
    release_type: patch # 'major', 'minor', or 'patch' - omit to auto-detect from git tags
    commit: "true"
    tag: "true"
    dry-run: "false"
    working-directory: "."
    config-file: ".bumpversion.toml"
OutputDescription
new_versionThe new version string after bumping
old_versionThe previous version string before bumping
release_typeThe component that was bumped (major/minor/patch)

§🔒 Safety

This crate enforces #![forbid(unsafe_code)] at the crate root (except the Node.js FFI layer which requires unsafe for napi-rs interop). Every byte of the implementation: config parsing, regex matching, version bumping, git object creation, is written in safe Rust.

§📊 Benchmarks

§CLI vs CLI: bump vs bump-my-version (hyperfine)

Measured with hyperfine --runs 5 --warmup 2 -N on x86-64 Linux (target-cpu=native release build):

ScenarioToolMeanMinMax
patch bumpbump (Rust)5.6 ms2.6 ms10.5 ms
minor bumpbump (Rust)3.9 ms2.8 ms6.2 ms
major bumpbump (Rust)2.5 ms1.9 ms3.2 ms
any bumpbump-my-version (Python)482.3 ms473.8 ms488.0 ms

CLI speedup: ~90-200× faster depending on scenario (major bump is fastest: ~193×).

At the library function level (pure parse+bump+serialize, no process startup):

BenchmarkRust (bump2version)Python (bump-my-version)Speedup
parse + bump + serialize~13 µs~79 µs~6×
Config parse (minimal)~12 µs~4 800 µs~400×
File replace, 10K lines~14 ms--
Full pipeline (CLI cold start)2.4 ms482 ms~200×

Run the comparison yourself:

# Rust
hyperfine --runs 10 -N "bump --config-file .bumpversion.toml --bump patch --dry-run"

# Python (if installed)
hyperfine --runs 10 "bump-my-version bump patch --dry-run"

# Full comparative suite
chmod +x benchmarks/hyperfine/run_comparison.sh
./benchmarks/hyperfine/run_comparison.sh

§Internal Benchmarks (cargo bench)

Run with cargo bench. Results on x86-64 Linux after optimization (LTO=fat, opt-level=3, target-cpu=native):

BenchmarkTime
config_parse/minimal~12 µs
config_parse/full_with_parts~18 µs
version_parse/1.0.0~430 ns
version_bump/patch~13 µs
version_bump/minor~14 µs
version_bump/major~6 µs
prerelease_bump/stage~15 µs
file_replace/100 lines~240 µs
file_replace/1 000 lines~1.3 ms
file_replace/10 000 lines~14 ms
file_replace/100 000 lines~140 ms
worst_case/10 000 lines~14 ms
multiline_replace/100x~85 µs

§📚 Further Reading

§📄 License

Licensed under the MIT License.

§bump2version Rust Documentation 🦀

The bump2version Rust crate provides a fully thread-safe, library-quality version bumper. All logic is available both as a CLI binary and as a library importable in other Rust projects.

§📦 Installation (CLI)

cargo install bump2version --features rust-binary

Note: This installs bump, cargo-bump, and the original bump2version executable. The latter is retained for backward compatibility with older tutorials.

§📦 Library Usage

[dependencies]
bump2version = { version = "0.2.2", default-features = false }

§🛠 Usage Overview

§Parse a version

use bump2version::config::BumpConfig;
use bump2version::version::parse_version;

let cfg = BumpConfig::default();
let v = parse_version("1.2.3", &cfg).unwrap();
assert_eq!(v["major"].value, "1");
assert_eq!(v["patch"].value, "3");

§Bump a version

use bump2version::config::BumpConfig;
use bump2version::version::{BumpPart, bump_version, serialize_version, parse_version};

let cfg = BumpConfig::default();
let v = parse_version("1.2.3", &cfg).unwrap();
let bumped = bump_version(&v, &BumpPart::Minor, &cfg).unwrap();
assert_eq!(serialize_version(&bumped, &cfg), "1.3.0");

§Parse config file

use bump2version::config::parse_config_file;

let cfg = parse_config_file(".bumpversion.toml").unwrap();
println!("{:?}", cfg.current_version);

§Apply file search/replace

use bump2version::config::{BumpConfig, FileConfig};
use bump2version::files::apply_file_change;

let cfg = BumpConfig::default();
let mut fc = FileConfig::new("Cargo.toml");
fc.search = Some(r#"name = "bump2version"\nversion = "{current_version}""#.to_string());
fc.replace = Some(r#"name = "bump2version"\nversion = "{new_version}""#.to_string());

let content = r#"name = "bump2version"\nversion = "1.0.0""#.to_string();
let updated = apply_file_change(&content, &fc, &cfg, "1.0.0", "1.0.1").unwrap();
assert!(updated.contains("1.0.1"));

§Read git author from local config

use bump2version::git::get_git_author;
use gix::open;

let repo = open(".").unwrap();
let (name, email) = get_git_author(&repo).unwrap();
println!("{name} <{email}>");

§Installation check

bump --version
# bump 0.2.1

bump2version --version
# bump2version 0.2.1  (backward-compatible alias)

cargo bump --help
# bump 0.2.1 : high-performance version bumper

§1. Patch / Minor / Major bump

bump --bump patch          # 0.2.1 → 0.2.2
bump --bump minor          # 0.2.1 → 0.3.0
bump --bump major          # 0.2.1 → 1.0.0

§2. Dry-run preview (no files written)

bump --bump patch --dry-run
bump --bump minor -n
# Output: [dry-run] Would commit 1 file(s) with message: Bump version: 0.2.1 → 0.2.2

§3. Explicit new version (skip bump calculation)

bump --new-version 2.0.0
bump --new-version 1.0.0-beta.1

§4. Override current version

bump --current-version 1.0.0 --bump patch

§5. Custom config file

bump --config-file path/to/.bumpversion.toml --bump patch
bump --config-file examples/python/.bumpversion.toml --bump minor --dry-run

§6. Git commit

bump --bump patch --commit

§7. Git commit + tag

bump --bump patch --commit --tag

§8. Custom commit message

bump --bump patch --commit --message "chore: release {new_version}"

§9. Extra files on the command line

bump --bump patch README.md CHANGELOG.md
bump --bump patch --dry-run src/main.rs

§10. Custom parse regex

bump --bump patch \
  --parse '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'

§11. Custom serialize format

bump --bump patch --serialize '{major}.{minor}.{patch}-dev'

§12. Combined: custom parse + serialize + dry-run

bump \
  --current-version "1.0.0-alpha.1" \
  --parse '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)-(?P<stage>[a-z]+)\.(?P<devnum>\d+)' \
  --serialize '{major}.{minor}.{patch}-{stage}.{devnum}' \
  --bump devnum \
  --dry-run
# [dry-run] Would bump 1.0.0-alpha.1 → 1.0.0-alpha.2

§13. Cargo subcommand

cargo bump --bump patch
cargo bump --bump minor --dry-run
cargo bump --new-version 2.0.0 --commit --tag

§14. Docker

docker run --rm -v "$(pwd):/workspace" wiseaidev/bump2version \
  --config-file /workspace/.bumpversion.toml \
  --bump patch \
  --dry-run

§15. Watch mode (requires watch feature)

# Monitors .bumpversion.toml and registered files; auto-bumps on save
bump --watch --bump patch

§16. Multi-language auto-detect (requires detect feature)

# Scans the directory tree for Cargo.toml, pyproject.toml, package.json, etc.
bump --bump patch --detect
bump --bump minor --detect --dry-run

§17. Backward-compatible bump2version binary

# All commands work identically on the bump2version alias:
bump2version --bump patch --dry-run
bump2version --bump minor
bump2version --new-version 2.0.0 --commit --tag

§🗂 Examples

All examples live under examples/ with pre-built .bumpversion.toml configs:

DirectoryLanguageKey Files
examples/rust-libRustCargo.toml
examples/pythonPythonpyproject.toml, setup.cfg
examples/nodejsNode.jspackage.json
examples/goGoVERSION, main.go
examples/javaJava (Maven)pom.xml
examples/rubyRuby.gemspec, Gemfile
examples/multi-langAll 6 at onceall of the above
examples/yew-appYew WASMbrowser UI

§Running any example

# From the project root:
bump --config-file examples/python/.bumpversion.toml --bump patch --dry-run

# From inside the example directory:
cd examples/nodejs
bump --bump minor --dry-run

§Detect mode across the multi-lang workspace

cd examples/multi-lang
bump --current-version 0.1.0 --bump patch --detect --dry-run
# [dry-run] Would update: Cargo.toml, pyproject.toml, package.json, VERSION, pom.xml, my-gem.gemspec

§📖 Module Overview

ModuleDescription
configParse .bumpversion.toml into BumpConfig, FileConfig, PartConfig
versionParse version strings, bump components, serialize back to string
filesApply single/multiline search-replace with {current_version} tokens
gitThread-safe git commit + tag via gix; reads author from git config
errorTyped BumpError enum
utilsHigher-level helpers: load_config, compute_new_version, collect_file_configs
workspaceAtomic workspace-aware bumping across all Cargo workspace members
detectMulti-language manifest scanner (requires detect feature)
watchFile-system watcher loop for auto-bumping (requires watch feature)
cliclap-based CLI argument struct (requires cli feature)
pythonPyO3 bindings (requires python feature)
nodenapi-rs bindings (requires node feature)

§🔗 See Also

§WebAssembly (WASM) Support 🌐

The bump2version core modules (config, version, files, error) natively compile to wasm32-unknown-unknown, no filesystem, no OS threads, no unsafe code. This makes them an excellent drop-in for browser-side version management tools, editor extensions, and Rust frontend apps.

§Framework Compatibility

Because the core logic has zero OS dependencies, bump2version works out-of-the-box with all major Rust frontend frameworks:

§📦 Usage

Add bump2version with no_std (no std feature) to your WASM project’s Cargo.toml:

[dependencies]
bump2version = { version = "0.2.2", default-features = false }

§Minimal Example (Yew)

The following component lets the user enter a version string and instantly see the bumped result, entirely in the browser with zero network requests:

use bump2version::config::BumpConfig;
use bump2version::version::{BumpPart, bump_version, parse_version, serialize_version};
use yew::prelude::*;

#[function_component(VersionBumper)]
pub fn version_bumper() -> Html {
    let version = use_state(|| "1.2.3".to_string());
    let result = use_state(|| "-".to_string());

    let on_bump = {
        let version = version.clone();
        let result = result.clone();
        Callback::from(move |part: &'static str| {
            let cfg = BumpConfig::default();
            if let Ok(parsed) = parse_version(&*version, &cfg) {
                if let Ok(bumped) = bump_version(&parsed, &BumpPart::from(part), &cfg) {
                    result.set(serialize_version(&bumped, &cfg));
                }
            }
        })
    };

    html! {
        <div class="bumper">
            <input
                value={(*version).clone()}
                oninput={Callback::from({
                    let version = version.clone();
                    move |e: InputEvent| {
                        let input: web_sys::HtmlInputElement = e.target_unchecked_into();
                        version.set(input.value());
                    }
                })}
                placeholder="e.g. 1.2.3"
            />
            <button onclick={on_bump.reform(|_| "patch")}>{ "Bump Patch" }</button>
            <button onclick={on_bump.reform(|_| "minor")}>{ "Bump Minor" }</button>
            <button onclick={on_bump.reform(|_| "major")}>{ "Bump Major" }</button>
            <p>{ format!("New version: {}", *result) }</p>
        </div>
    }
}

#[function_component(App)]
pub fn app() -> Html {
    html! { <VersionBumper /> }
}

// fn main() {
//     yew::Renderer::<App>::new().render();
// }

§Full Yew App Example

A reference implementation of a version-bump UI tool built with Yew and bump2version is available in examples/yew-app. It includes:

  • Input field for the current version
  • Patch / Minor / Major bump buttons
  • Pre-release cycling (alpha → beta → rc → stable) via custom BumpConfig
  • Live output of the new version string

§Running the Example

cd examples/yew-app
cargo install trunk
trunk serve --port 3000
# Open http://localhost:3000 in your browser

§Limitations

The WASM build excludes:

ModuleAvailable in WASM?Reason
config✅no_std + alloc
version✅no_std + alloc
files✅no_std + alloc
error✅no_std + alloc
git❌requires std::fs and OS APIs
watch❌requires OS file-system events
detect❌requires walkdir + filesystem
CLI❌requires std::env

§Example: Building a Version Management Tool

You can use bump2version as the versioning backend for a browser-based release management dashboard. A reference Yew application is in examples/yew-app demonstrating full pre-release lifecycle management in the browser.

Modules§

clicli and std
CLI Argument Definitions
config
Configuration Parsing
detectcli and detect and std
Multi-Language Version Auto-Detection
error
Error Types
files
File Search and Replace
gitgit
Git Integration
nodenode and std
Node.js Bindings
utilsstd
Utility Helpers
version
Version Parsing and Bumping
watchcli and std and watch
Watch Mode
workspacestd
Workspace-Aware Bumping