bump2versionis the world's fastest version bumper written entirely in 100% safe Rust, withno_stdsupport, native Python and Node.js bindings, and acargo bumpsubcommand 🗿.
| Platform | Command |
|---|---|
| Rust binary | cargo install bump2version --features rust-binary |
| Cargo subcommand | cargo bump --help |
| Docker | docker pull wiseaidev/bump2version |
| Debian/Ubuntu | Download .deb from GitHub Releases |
| RHEL/Fedora | Download .rpm from GitHub Releases |
| Windows | Download bump.exe from GitHub Releases |
| GitHub Action | See action.yml |
| Python | pip install bump-rs |
| Node.js | npm 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.
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 likealpha → 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.
# 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| Option | Description |
|---|---|
--config-file |
Config file path (default: .bumpversion.toml) |
--current-version |
Override current version |
--bump |
Component: major, minor, patch, or any custom part |
--parse |
Parse regex override |
--serialize |
Serialize format override |
--dry-run / -n |
Simulate without writing files |
--new-version |
Explicit new version (skips bump calculation) |
--commit / --tag |
Git commit + lightweight tag |
| Feature | Default | Description |
|---|---|---|
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 |
The Rust crate is available on crates.io. For a complete API reference visit RUST.md.
[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
}Core modules (config, version, files, error) compile in no_std + alloc:
bump2version = { version = "0.2.2", default-features = false }| Module | no_std+alloc |
std |
|---|---|---|
config |
✅ | ✅ |
version |
✅ | ✅ |
files |
✅ | ✅ |
error |
✅ | ✅ |
git |
❌ | ✅ |
| CLI | ❌ | ✅ |
| Python / Node.js | ❌ | ✅ |
pip install bump-rsfrom 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.
npm install bump2versionconst { bumpVersion, applyFileChange } = require("bump2version");
console.log(bumpVersion("1.2.3", "patch")); // '1.2.4'For full docs see NODE.md.
[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"""[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# Atomically bump all workspace member crates
bump --bump patchThe workspace module discovers all [workspace] members and bumps every Cargo.toml in one pass.
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"| Output | Description |
|---|---|
new_version |
The new version string after bumping |
old_version |
The previous version string before bumping |
release_type |
The component that was bumped (major/minor/patch) |
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.
Measured with hyperfine --runs 5 --warmup 2 -N on x86-64 Linux (target-cpu=native release build):
| Scenario | Tool | Mean | Min | Max |
|---|---|---|---|---|
| patch bump | bump (Rust) |
5.6 ms | 2.6 ms | 10.5 ms |
| minor bump | bump (Rust) |
3.9 ms | 2.8 ms | 6.2 ms |
| major bump | bump (Rust) |
2.5 ms | 1.9 ms | 3.2 ms |
| any bump | bump-my-version (Python) |
482.3 ms | 473.8 ms | 488.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):
| Benchmark | Rust (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 ms | 482 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.shRun with cargo bench. Results on x86-64 Linux after optimization (LTO=fat, opt-level=3, target-cpu=native):
| Benchmark | Time |
|---|---|
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 |
- CLI.md: Full CLI command dictionary
- RUST.md: Rust API guide
- PYTHON.md: Python bindings guide
- NODE.md: Node.js bindings guide
- DOCKER.md: Docker usage guide
- WASM.md: WebAssembly + Yew guide
- PACKAGING.md: Debian/RPM packaging
- examples/yew-app: Browser-side version bumper (Yew + WASM)
- Semantic Versioning 2.0.0
- bump-my-version: the Python tool this crate is feature-parity with
- gitoxide (gix): the pure-Rust git implementation
Licensed under the MIT License.

