A command-line tool for creating and managing coordinated patch series across multiple Git repositories
Project description
changes-roller
Stop manually patching dozens of repositories. Automate it.
Changes-Roller is a command-line tool for creating and managing coordinated patch series across multiple Git repositories simultaneously.
Why changes-roller?
When you need to apply the same change across multiple repositories—whether it's a security patch, dependency update, or configuration change—doing it manually is time-consuming and error-prone. You have to clone each repository, apply the change, commit, and submit for review, repeating this process dozens of times.
changes-roller automates this workflow. Write your patch script once, and it executes across all repositories in parallel. Changes are applied consistently with uniform commit messages, and optionally submitted for code review—all from a single command.
Perfect for:
- Security updates across multiple microservices
- Dependency upgrades throughout your service ecosystem
- API migrations affecting client libraries
- License header updates for compliance
- Configuration file standardization
- Any scenario requiring identical changes across multiple repositories
Project Status
This project maintains high quality standards through automated testing and continuous integration:
- Comprehensive test suite with high code coverage
- Multi-platform testing across Python 3.10-3.13 on Linux, macOS, and Windows
- Automated quality checks including strict type checking (MyPy), linting (Ruff), and security scanning (Bandit)
- Pre-commit hooks enforce code quality before commits
- Continuous security monitoring with pip-audit and dependency review
All pull requests undergo comprehensive automated testing to ensure reliability and maintainability.
How It Works
Configure once, execute everywhere. You provide the repositories to update and a script containing your changes. changes-roller handles everything else—cloning, patching, testing, committing, and submitting for review. Parallel execution means 50 repositories finish almost as quickly as one. Built-in error handling ensures you get clear feedback about any issues, while successful repositories continue processing.
Features
- Apply patches to multiple Git repositories in parallel
- Custom patch scripts with full repository access
- Automated Git operations (clone, commit, stage)
- Git branch switching - Apply changes to specific branches (e.g., stable branches)
- Custom command execution - Run commands before/after applying changes
- Dry-run mode - Preview operations without executing them
- Automatic commit sign-off (Signed-off-by line)
- Automatic git-review setup for Gerrit integration
- Commit message templating with variables
- Gerrit code review integration with topic grouping
- Optional test execution before committing (e.g.,
tox -e pep8) - Clear progress reporting and error handling
Installation
# Install in development mode
pip install -e .
# Or install from source
pip install .
Requirements
- Python 3.10 or higher
- Git command-line client
- git-review (optional, for Gerrit integration)
Quick Start
- Generate a configuration file:
roller init --output my-series.ini
- Create a patch script (
my_patch.sh):
#!/bin/bash
# Example: Update a dependency version
sed -i 's/old-library==1.0/old-library==2.0/' requirements.txt
chmod +x my_patch.sh
- Edit the configuration file to specify your repositories and patch script:
nano my-series.ini
# Update the 'projects' list and 'commands' path
- Run the patch series:
roller create --config-file my-series.ini
Configuration
[SERIE] Section
Basic Options:
projects(required): Comma-separated list of Git repository URLscommands(required): Path to executable patch scriptcommit_msg(required): Commit message template (supports{{ project_name }})topic(optional): Code review topic namecommit(optional): Enable automatic commits (default: true)review(optional): Enable Gerrit review submission (default: false)
Branch Switching Options:
branch(optional): Target branch to switch to before applying changescreate_branch(optional): Create branch if it doesn't exist (default: false)stay_on_branch(optional): Don't return to original branch after completion (default: false)
Command Execution Options:
pre_commands(optional): Commands to run before applying changes (one per line)post_commands(optional): Commands to run after committing (one per line)continue_on_error(optional): Continue if commands fail (default: false)dry_run(optional): Preview operations without executing (default: false)
[TESTS] Section
run(optional): Enable test execution (default: false)blocking(optional): Fail if tests fail (default: false)command(optional): Test command to run (default: tox)
Example: command = tox -e pep8 runs PEP8 checks before committing
Command-Line Options
roller init
Generate a template configuration file.
roller init [options]
Options:
-o, --output PATH Output file path (default: series.ini)
-f, --force Overwrite existing file
--help Show help message
roller create
Create a new patch series across multiple repositories.
roller create --config-file <path> [options]
Options:
--config-file PATH Path to configuration file (required)
--config-dir PATH Additional directory for config files
-e, --exit-on-error Exit immediately on first failure
-v, --verbose Enable verbose output
# Branch switching
--branch NAME Target branch to switch to before applying changes
--create-branch Create branch if it doesn't exist (requires --branch)
--stay-on-branch Don't return to original branch after completion
# Command execution
--pre-command CMD Command to execute before changes (repeatable)
--post-command CMD Command to execute after changes (repeatable)
--continue-on-error Continue if commands fail instead of stopping
--dry-run Preview operations without executing them
--help Show help message
Examples
Basic Usage
# Apply patch to multiple repositories
roller create --config-file my-series.ini
Branch Switching
# Apply changes to a specific branch
roller create --config-file security-fix.ini --branch stable/2024.2
# Multi-branch backport
for branch in stable/2024.1 stable/2024.2 stable/2025.1; do
roller create --config-file fix.ini --branch $branch
done
With Commands
# Pull latest before patching, push after committing
roller create --config-file series.ini \
--pre-command "git pull origin main" \
--post-command "git push origin main"
# Validate before and after
roller create --config-file series.ini \
--pre-command "pytest tests/" \
--post-command "git push"
Dry Run
# Preview what would happen without executing
roller create --config-file series.ini --dry-run
With Testing
Configuration file with PEP8 validation:
[SERIE]
projects = https://github.com/org/repo1,
https://github.com/org/repo2
commands = ./my-patch.sh
commit_msg = Fix styling in {{ project_name }}
[TESTS]
run = true
blocking = true
command = tox -e pep8
Examples
See the examples/ directory for complete working examples:
Dependency Update - Template
Generic example showing how to update dependencies across multiple repos. Uses placeholder repository URLs - copy and customize for your own projects.
Oslo Dependency Update - Real Example
Update pbr dependency across oslo.* libraries. Uses real OpenStack repositories and demonstrates Gerrit integration.
Each example includes:
- Complete patch script with error handling
- Configured series.ini file
- README with usage instructions and customization guide
For more examples and use cases, see the documentation examples page.
Development
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Format code
ruff format .
# Linting
ruff check .
# Type checking
mypy roller/
Contributing
We welcome contributions! Please see our contributing guidelines and community standards:
- Contributing Guide - Development setup, code standards, and PR process
- Code of Conduct - Community standards and expectations
- Changelog - Release history and version changes
- Security Policy - Reporting issues and safe usage guidelines
License
See LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file changes_roller-0.2.0.tar.gz.
File metadata
- Download URL: changes_roller-0.2.0.tar.gz
- Upload date:
- Size: 1.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e2fd8bd34705e3261512300d7a2da97368b09aa3d07d422926b608f386fe95e
|
|
| MD5 |
daefa5f5c5c635c4df453b3752beb80f
|
|
| BLAKE2b-256 |
f4033155bf8ac658bcf15d0563e32bbf1d211d7186d41ae3b520698b63ce8a85
|
Provenance
The following attestation bundles were made for changes_roller-0.2.0.tar.gz:
Publisher:
release.yml on k-pavlo/changes-roller
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
changes_roller-0.2.0.tar.gz -
Subject digest:
7e2fd8bd34705e3261512300d7a2da97368b09aa3d07d422926b608f386fe95e - Sigstore transparency entry: 969435685
- Sigstore integration time:
-
Permalink:
k-pavlo/changes-roller@9275a56bf614c4954d584e646686b3696b8be95c -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/k-pavlo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9275a56bf614c4954d584e646686b3696b8be95c -
Trigger Event:
push
-
Statement type:
File details
Details for the file changes_roller-0.2.0-py3-none-any.whl.
File metadata
- Download URL: changes_roller-0.2.0-py3-none-any.whl
- Upload date:
- Size: 20.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6efaa8891e74de1e2efaa08ebba3f24be509fedb83a4cc15a6935f0a34a3a280
|
|
| MD5 |
608953bc5913210aeaf90c8923ca90a3
|
|
| BLAKE2b-256 |
5fbd103a58fb4ea36ff376e8931be1070d1b25512b5d0285560d4e69a2c9d2af
|
Provenance
The following attestation bundles were made for changes_roller-0.2.0-py3-none-any.whl:
Publisher:
release.yml on k-pavlo/changes-roller
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
changes_roller-0.2.0-py3-none-any.whl -
Subject digest:
6efaa8891e74de1e2efaa08ebba3f24be509fedb83a4cc15a6935f0a34a3a280 - Sigstore transparency entry: 969435689
- Sigstore integration time:
-
Permalink:
k-pavlo/changes-roller@9275a56bf614c4954d584e646686b3696b8be95c -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/k-pavlo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9275a56bf614c4954d584e646686b3696b8be95c -
Trigger Event:
push
-
Statement type: