Command-line tool for the management of pull requests in a GitHub organization and changes on Gerrit Code Review servers.
| Command | Description |
|---|---|
| merge | Bulk approve/merge pull requests (GitHub) or changes (Gerrit) |
| close | Bulk close pull requests across a GitHub organization |
| blocked | Reports blocked pull requests in a GitHub organization |
| status | Reports repository statistics for tags, releases, and PRs |
Bulk approves/merges similar pull requests across different repositories in a GitHub organisation, or similar changes on a Gerrit Code Review server.
By default, bypasses code owner review requirements to enable automated merging of dependency updates. Supports common automation tools:
- Dependabot
- pre-commit.ci
- Renovate
- GitHub Copilot
Also works for individual GitHub users when provided with an override flag.
Matches pull requests based on a heuristic that considers the criteria:
- Pull requests created by the same author/automation
- Pull requests with the same title/body content
- Pull requests containing the same package updates
- Pull requests changing the same files
When provided with a Gerrit change URL, the tool will:
- Detect the Gerrit server and authenticate using credentials
- Fetch details of the source change
- Search for similar open changes on the same server
- Apply +2 Code-Review and submit matching changes
Gerrit URL format:
https://gerrit.example.org/c/project/name/+/12345
https://gerrit.example.org/base/c/project/name/+/12345
The tool automatically detects whether a URL is for GitHub or Gerrit based on
the URL pattern (/pull/ for GitHub, /c/.../+/ for Gerrit).
Reports repository statistics across a GitHub organization, including:
- Latest tags and releases with synchronization status
- Open and merged pull request counts
- Pull requests affecting action files or workflow configurations
- Separate counts for human contributors and automation tools
Helps track release management and identify repositories needing attention. Supports both table and JSON output formats.
Lists blocked pull requests across a GitHub organization. Useful when successive merges have created conflicts or the need to rebase. Also lists pull requests blocked by branch protection rules, such as those with failed CI jobs, tests, etc.
Bulk closes similar pull requests across different repositories in a GitHub organisation. Works with the same automation tools as merge:
- Dependabot
- pre-commit.ci
- Renovate
- GitHub Copilot
Also works for individual GitHub users when provided with an override flag.
Uses the same matching heuristic as merge to find similar PRs. Unlike merge, it requires PRs to be in the open state (no mergeable state checks needed).
Dependamerge provides four main functions:
- Finding Blocked PRs: Check entire GitHub organizations to identify pull requests with conflicts, failing checks, or other blocking issues
- Automated Merging (GitHub): Analyze a source pull request and find similar pull requests across all repositories in the same GitHub organization, then automatically approve and merge the matching PRs
- Automated Merging (Gerrit): Analyze a source change on a Gerrit Code Review server, find similar open changes, then apply +2 Code-Review and submit matching changes
- Bulk Closing: Analyze a source pull request and find similar pull requests across all repositories in the same GitHub organization, then close all matching open PRs
This saves time on routine dependency updates, maintenance tasks, and coordinated changes across all repositories while providing visibility into unmergeable PRs that need attention.
Works with any pull request or change regardless of author, automation tool, or origin. The tool automatically detects whether a URL is for GitHub or Gerrit based on the URL pattern.
- Comprehensive PR Analysis: Checks all repositories in a GitHub organization for unmergeable pull requests
- Blocking Reason Detection: Identifies specific reasons preventing PR merges (conflicts, failing checks, blocked reviews)
- Copilot Integration: Counts unresolved GitHub Copilot feedback comments (column shown when present)
- Smart Filtering: Excludes standard code review requirements, focuses on technical blocking issues
- Detailed Reporting: Provides comprehensive tables and summaries of problematic PRs
- Real-time Progress: Live progress display shows checking status and current operations
- Universal PR Support: Works with any pull request regardless of author or automation tool
- Smart Matching: Uses content similarity algorithms to match related PRs across repositories
- Bulk Operations: Approve and merge related similar PRs with a single command
- Security Features: SHA-based authentication for non-automation PRs ensures authorized bulk merges
- Interactive Mode by Default: Preview what changes will apply, then optionally proceed with merge
Pass a bare owner URL (e.g. https://github.com/lfreleng-actions) to merge
every in-scope automation pull request across an entire GitHub organisation
or user account in one command.
- Owner-Wide Scope: Enumerates every repository owned by the
organisation or user, then bulk merges their open automation PRs
(
dependabot,pre-commit,renovate, and other recognised bots) - Organisation or User: Detects the account type (org vs user) automatically at runtime; the same URL works for both
- Archived and Fork Exclusion: Skips archived repositories, and excludes fork repositories by default (owner-wide merges target the owner's own repositories, not mirrored forks)
- Striped Sequencing: Schedules merges so that at most one PR per repository runs at a time while distinct repositories run concurrently. This spreads ("stripes") work across repositories and structurally avoids the data-replication races that otherwise arise when two same-repository PRs land back-to-back — without injected delays or random retries
- Drain Ordering: Orders repositories with the most PRs first (they take longest to drain), and merges PRs oldest-number-first within a repository to match the order dependabot expects to rebase
- Self-Rebase Awareness: Detects when dependabot has begun rebasing a
sibling PR (the "Dependabot is rebasing this PR" banner), holds that PR
in a background wait, and lets auto-merge land it rather than failing it
or firing a redundant rebase macro. A global
--max-waitceiling bounds the whole run - Resilient Enumeration: The run reports and skips a transient failure scanning one repository, then continues with the repositories it scanned
- Cumulative Activity Counters: The live progress line reports
⬆️ Rebased(rebase operations triggered — local force-push, RESTupdate-branch, or the@dependabot rebasemacro) and📣 Retriggered(comment macros posted:@dependabot rebase,@dependabot recreate,pre-commit.ci run). Both are running totals of operations, so they keep reporting what the run did after the PRs themselves have landed in✅ Merged/❌ Failed - Grouped Preview: The preview lists candidate PRs grouped by repository for readability, then prompts for a confirmation token before merging
- Human PR Safety: The run excludes human-authored PRs by default;
passing
--include-human-prsbrings them into scope behind an explicit confirmation prompt covering the entire owner
Note: Owner-wide merging supports
github.comalone for now. GitHub Enterprise Server support exists in scaffold form but remains disabled.
- Rich CLI Output: Beautiful terminal output with progress indicators and tables
- Real-time Progress: Live progress updates for both checking and merge operations
- Output Formats: Support for table and JSON output formats
- Error Handling: Graceful handling of API rate limits and repository access issues
- Any pull request from any author
- Manual pull requests from developers
- Automation tool pull requests (Dependabot, Renovate, etc.)
- Bot-generated pull requests
- Coordinated changes across repositories
This project uses:
- hatchling + hatch-vcs for dynamic (tag-based) versioning
- uv for environment + dependency management (produces/consumes
uv.lock)
Use uvx to run the latest published version directly from PyPI
(no virtualenv management needed):
# Show help (latest release)
uvx dependamerge --help
# Run a specific tagged release
uvx dependamerge==0.1.0 merge https://github.com/owner/repo/pull/123# 1. Install uv (if not already installed)
# macOS/Linux (script):
curl -LsSf https://astral.sh/uv/install.sh | sh
# or with pipx:
pipx install uv
# 2. Clone the repository
git clone <repository-url>
cd dependamerge
# 3. Create & activate a virtual environment (optional but recommended)
uv venv .venv
source .venv/bin/activate # (On Windows: .venv\Scripts\activate)
# 4. Install project + dev dependencies (uses dependency group 'dev')
uv sync --group devThe first sync will generate uv.lock. Commit that file to ensure reproducible
builds.
uv sync installs the project in editable (PEP 660) mode automatically.
After making changes you can run:
uv run dependamerge --helpDynamic version comes from Git tags (e.g. tag v0.2.0 → version 0.2.0):
# Build wheel + sdist
uv build
# (Optional) Inspect dist/
ls dist/
# Publish to PyPI (ensure you have credentials configured)
uv publishIf you build before tagging, a local scheme like 0.0.0+local
(or similar) may appear—tag first for clean releases.
Edit pyproject.toml and then:
uv syncTo add a dev dependency:
uv add --group dev pytest-cov# Run a specific version in an ephemeral environment
uvx dependamerge==0.1.0 --helpDependamerge supports both GitHub and Gerrit platforms, each with different authentication requirements.
You need a GitHub personal access token with appropriate permissions. The tool performs both read and write operations on GitHub repositories and pull requests.
Dependamerge supports both classic and fine-grained personal access tokens.
To configure a GitHub personal access token for use with dependamerge, go to:
Then:
Profile → Settings → Developer settings → Personal access tokens
Fine-grained tokens → Generate new token
Required Repository Permissions:
- Contents: Read and write (for merging PRs and accessing file changes)
- Pull requests: Read and write (for creating reviews, approving, and merging)
- Workflows: Read and write (for PRs that change GitHub Actions workflows)
- Administration: Read access (for reading branch protection rules)
- Metadata: Read access (automatically included)
Required Account Permissions:
- Organization members: Read access (to access organization repositories)
Repository Access:
- Select "All repositories" or specify which repositories to access
Required Scopes:
read:org- Read organization membership, teams, and repositoriesworkflow- Update GitHub Actions workflows (needed for PRs modifying workflows)
One of the two options below is also needed:
public_repo- Access to public repositories (if working with public repos)repo- Full control of private repositories (includes all repository permissions)
- Read Operations: Access PR details, file changes, reviews, commits, check runs, and repository lists
- Write Operations: Create PR reviews (approvals), merge pull requests, update PR branches
Important Notes for Branch Protection:
- If repositories have branch protection rules enabled, these
requirements may apply:
- Required status checks: All CI/CD workflows must pass before merging
- Required reviews: PRs may need approval from code owners or specific teams
- Up-to-date branches: PRs may need to be current with the base branch
- Copilot review resolution: When using
--dismiss-copilot, the tool automatically handles all review types using dismissal or thread resolution as appropriate
- Default behavior: By default, dependamerge uses
--force=code-ownersto bypass code owner review requirements for automation PRs - For repositories with strict branch protection, use
--force=protection-rulesor--force=all, though the token owner may need admin permissions on individual repositories to bypass certain rules
Set the token as an environment variable:
export GITHUB_TOKEN=your_token_hereOr pass it directly to the command using --token.
To verify your token has the correct permissions:
# Test basic access
curl -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user
# Test organization access
curl -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/orgs/YOUR_ORG/reposGerrit Code Review servers require HTTP credentials for API access. These are typically different from your SSO/LDAP login credentials.
- Log into your Gerrit server web interface
- Navigate to: Settings → HTTP Credentials
- Generate a new HTTP password if you don't have one
- Note your HTTP username (often your email or username)
Set the credentials as environment variables:
export GERRIT_USERNAME="your_username"
export GERRIT_PASSWORD="your_http_password"Alternative environment variable names are also supported for compatibility:
export GERRIT_HTTP_USER="your_username"
export GERRIT_HTTP_PASSWORD="your_http_password"Note: The GERRIT_USERNAME/GERRIT_PASSWORD variables take precedence
over GERRIT_HTTP_USER/GERRIT_HTTP_PASSWORD when you configure both.
To verify your Gerrit credentials:
# Test basic access (replace with your Gerrit server)
curl -u "$GERRIT_USERNAME:$GERRIT_PASSWORD" \
"https://gerrit.example.org/a/accounts/self"A successful response returns your account details in JSON format (with a
)]}'\n XSSI guard prefix that Gerrit adds to all JSON responses).
Dependamerge supports loading Gerrit credentials from .netrc files, following
the standard format used by curl and other tools.
Search order:
.netrcin the current directory~/.netrcin your home directory~/_netrc(Windows fallback)
Example .netrc file:
machine gerrit.onap.org login myuser password mytoken
machine gerrit.opendaylight.org login myuser password anothertoken
CLI options:
| Option | Description |
|---|---|
--no-netrc |
Disable .netrc file lookup |
--netrc-file PATH |
Use a specific .netrc file |
--netrc-optional |
Do not fail if .netrc file is missing (default) |
--netrc-required |
Require a .netrc file and fail if missing |
By default, .netrc lookup is optional (--netrc-optional): if no .netrc
file exists, the tool continues and falls back to environment variables.
Use --netrc-required to enforce that a .netrc file must be present.
When a .netrc file is present, the tool loads credentials automatically.
Explicit environment variables or CLI arguments take precedence over .netrc
entries.
Close pull requests across an entire GitHub organization:
# Close similar PRs from automation tools (dependabot, pre-commit.ci)
dependamerge close https://github.com/myorg/repo1/pull/45
# Close with no confirmation (immediate closing)
dependamerge close https://github.com/myorg/repo1/pull/45 --no-confirm
# Close with custom similarity threshold
dependamerge close https://github.com/myorg/repo1/pull/45 --threshold 0.9
# Close user-generated PRs with override SHA
dependamerge close https://github.com/myorg/repo1/pull/45 --override a1b2c3d4e5f6g7h8The close command will:
- Analyze the provided PR
- Find similar PRs across the organization
- Close all matching PRs that are in the open state
- Skip PRs that are already closed or are drafts
Note: Unlike the merge command, the close command does not need to check mergeable state or branch protection rules. It requires PRs to be in the open state.
Report statistics for tags, releases, and pull requests:
# Basic organization status check
dependamerge status myorganization
# Using full GitHub URL
dependamerge status https://github.com/myorganization/
# Check with JSON output
dependamerge status myorganization --format json
# Disable real-time progress display
dependamerge status myorganization --no-progressThe status command will:
- Scan all repositories in the organization
- Report latest tags and releases with sync status indicators
- Count open and merged PRs (split by human/automation)
- Identify PRs affecting action files or workflow configurations
Status icons:
- ✅ Tag has matching release
⚠️ Tag exists but no matching release- ❌ Release is more recent than tag
Find blocked pull requests in an entire GitHub organization:
# Basic organization check for blocked PRs
dependamerge blocked myorganization
# Using full GitHub URL
dependamerge blocked https://github.com/myorganization/
# Check with JSON output
dependamerge blocked myorganization --format json
# Disable real-time progress display
dependamerge blocked myorganization --no-progressThe blocked command will:
- Analyze all repositories in the organization
- Identify PRs with technical blocking issues
- Report blocking reasons (merge conflicts, failing workflows, etc.)
- Count unresolved GitHub Copilot feedback comments (displayed when present)
- Exclude standard code review requirements from blocking reasons
The merge command supports both GitHub PRs and Gerrit changes. The platform is automatically detected from the URL format.
dependamerge merge \
https://github.com/lfreleng-actions/python-project-name-action/pull/22# Set credentials first
export GERRIT_USERNAME="your_username"
export GERRIT_PASSWORD="your_http_password"
# Merge similar changes
dependamerge merge \
https://gerrit.linuxfoundation.org/infra/c/releng/lftools/+/12345For extra security, you can use the --override flag with SHA-based validation:
dependamerge merge https://github.com/owner/repo/pull/123 \
--override a1b2c3d4e5f6g7h8The SHA hash derives from:
- The PR author's GitHub username
- The first line of the commit message
- This provides an extra layer of validation for sensitive operations
By default, dependamerge runs in interactive mode showing you what PRs the tool will merge, then prompts you to continue:
dependamerge merge https://github.com/owner/repo/pull/123Interactive Flow:
- Analyzes and shows similar PRs that the tool will merge
- Displays merge evaluation results
- Generates a unique SHA for security validation
- Prompts you to enter the SHA to proceed with actual merging
- Merges PRs that appear as "mergeable" in the preview
Example Output:
🔍 Dependamerge Evaluation
✅ Approve/merge: https://github.com/org/repo1/pull/45
⏭️ Skipped: https://github.com/org/repo2/pull/67 [cannot update protected ref]
✅ Approve/merge: https://github.com/org/repo3/pull/89
▶️ Mergeable 2/3 PRs
➡️ To proceed with merging enter: abc123def456
Enter the string above to continue (or press Enter to cancel):
🚀 Merging 2 pull requests...
▶️ Merging PRs in org (2/2 PRs, 100%)
✅ Merged: 2
⏱️ Elapsed: 16s
🚀 Final Results: 2 merged, 0 failedUse --dry-run to perform a complete analysis and preview without making any
changes. A dry run never approves, merges, rebases, or closes anything, and it
skips the write-permission pre-flight check, so it runs under a token without
write access. This makes it ideal for CI validation and for inspecting what
the tool would do before committing to it:
# Preview a single PR (and its similar PRs) without merging
dependamerge merge https://github.com/owner/repo/pull/123 --dry-run
# Preview an owner-wide run under a token without write access
dependamerge merge https://github.com/owner --dry-run --no-progress
# Preview which PRs close would target, without closing them
dependamerge close https://github.com/owner/repo/pull/123 --dry-run
# Preview a Gerrit change without applying +2 or submitting
dependamerge merge https://gerrit.example.org/c/project/+/12345 --dry-runThe repository's Integration Tests (dry-run) workflow exercises every
sub-command in this mode against live GitHub (and, when configured, Gerrit)
on each pull request, so it catches owner-resolution and command regressions
before release. The integration suite self-skips when credentials or open
automation PRs are absent, so it never fails on an empty target space.
dependamerge merge https://github.com/owner/repo/pull/123 \
--threshold 0.9 \
--merge-method squash \
--no-fix \
--no-progress \
--token your_github_token--format TEXT: Output format - table or json (default: table)--progress/--no-progress: Show real-time progress updates (default: progress)--token TEXT: GitHub token (alternative to GITHUB_TOKEN env var)
--format TEXT: Output format - table or json (default: table)--progress/--no-progress: Show real-time progress updates (default: progress)--token TEXT: GitHub token (alternative to GITHUB_TOKEN env var)
General Options:
--no-confirm: Skip confirmation prompt and merge without delay (default is interactive mode)--dry-run: Analyze and preview without making changes - never approve, merge, rebase, or close anything. Skips the write-permission pre-flight so it runs under a token without write access (e.g. in CI). Implies preview mode and suppresses confirmation prompts. Works for GitHub PR, repository, and owner-wide URLs as well as Gerrit changes.--threshold FLOAT: Similarity threshold for matching PRs/changes (0.0-1.0, default: 0.8)--progress/--no-progress: Show real-time progress updates (default: progress)--verbose,-v: Enable verbose debug logging
GitHub-Specific Options:
--merge-method TEXT: Merge method - merge, squash, or rebase (default: merge)--no-fix: Disable automatic fixing of out-of-date branches (default: automatic fixing enabled)--dismiss-copilot: Automatically resolve unresolved GitHub Copilot reviews (dismissal + thread resolution)--force TEXT: Override level for bypassing safety checks -none(default),code-owners,protection-rules, orall. See Force Override System for detailed documentation--token TEXT: GitHub token (alternative to GITHUB_TOKEN env var)--override TEXT: SHA hash for extra security validation
Owner-Wide Options:
--max-wait SECONDS: Global wall-clock ceiling for an owner-wide run (default: 900, 15 minutes). Clamps every per-PR auto-merge wait so the run cannot hang on slow CI. Set--max-wait 0for fire-and-forget: approve, arm auto-merge, report each PR as pending, and return at once without blocking (GitHub completes the merges after the tool exits). Applies to owner-wide runs; single-PR and single-repo modes ignore it.
Gerrit Environment Variables:
GERRIT_USERNAME: HTTP username for Gerrit authenticationGERRIT_PASSWORD: HTTP password for Gerrit authentication
Fallback variables:
GERRIT_HTTP_USER: HTTP username (fallback)GERRIT_HTTP_PASSWORD: HTTP password (fallback)
--no-confirm: Skip confirmation prompt and close without preview--dry-run: Analyze and preview without making changes - never close anything. Suppresses the confirmation prompt so it runs unattended under a token without write access (e.g. in CI).--threshold FLOAT: Similarity threshold for matching PRs (0.0-1.0, default: 0.8)--progress/--no-progress: Show real-time progress updates (default: progress)--debug-matching: Show detailed scoring information for PR matching--token TEXT: GitHub token (alternative to GITHUB_TOKEN env var)--override TEXT: SHA hash to override non-automation PR restriction
- Parse Source PR: Analyzes the provided pull request URL and extracts metadata
- Organization Check: Lists all repositories in the same GitHub organization
- PR Discovery: Finds all open pull requests in each repository
- Content Matching: Compares PRs using different similarity metrics:
- Title similarity (normalized to remove version numbers)
- File change patterns
- Author matching
- Optional Validation: If
--overrideprovided, validates SHA for extra security - Approval & Merge: For matching PRs above the threshold:
- Adds an approval review
- Merges the pull request
- Source PR Merge: Merges the original source PR that served as the baseline
The tool uses different algorithms to determine if PRs are similar:
- Removes version numbers (e.g., "1.2.3", "v2.0.0")
- Removes commit hashes
- Removes dates
- Normalizes whitespace
- Compares changed filenames using Jaccard similarity
- Accounts for path normalization
- Ignores version-specific filename differences
Combines different factors:
- Title similarity score
- File change similarity score
- Author matching (same automation tool)
# Check organization for blocked PRs
dependamerge blocked myorganization
# Get detailed JSON output
dependamerge blocked myorganization --format json > unmergeable_prs.json
# Check without progress display
dependamerge blocked myorganization --no-progress# Merge a dependency update across all repos
dependamerge merge https://github.com/myorg/repo1/pull/45# Merge documentation updates
dependamerge merge https://github.com/myorg/repo1/pull/12 --threshold 0.85# Merge with optional security validation
dependamerge merge https://github.com/myorg/repo1/pull/89 \
--override f1a2b3c4d5e6f7g8# Set up Gerrit credentials
export GERRIT_USERNAME="your_username"
export GERRIT_PASSWORD="your_http_password"
# Merge similar changes on a Gerrit server
dependamerge merge \
https://gerrit.linuxfoundation.org/infra/c/releng/lftools/+/12345# Merge with higher similarity threshold
dependamerge merge \
https://gerrit.example.org/c/project/name/+/67890 \
--threshold 0.9# Skip confirmation prompt for automation
dependamerge merge --no-confirm \
https://gerrit.linuxfoundation.org/infra/c/releng/global-jjb/+/74080The --dismiss-copilot flag automatically resolves blocking Copilot reviews
using the most appropriate method:
# Merge with automatic Copilot review resolution (interactive mode)
dependamerge merge https://github.com/myorg/repo1/pull/67 --dismiss-copilot
# Interactive mode to see which Copilot items the tool will resolve, then
# choose to proceed (default behavior)
dependamerge merge https://github.com/myorg/repo1/pull/67 --dismiss-copilot
# Skip confirmation and merge without delay with Copilot dismissal
dependamerge merge https://github.com/myorg/repo1/pull/67 --dismiss-copilot --no-confirmComprehensive Resolution Strategy: The tool automatically uses the most appropriate method for each Copilot review:
- ✅ APPROVED reviews → Dismissed via GitHub API
- ✅ CHANGES_REQUESTED reviews → Dismissed via GitHub API
- ✅ COMMENTED reviews → Individual review threads resolved automatically
- ✅ Automatic fallback → No manual intervention required
The tool intelligently handles GitHub API limitations by automatically falling back to thread-level resolution for COMMENTED reviews, ensuring comprehensive coverage without requiring user intervention.
# See what changes will apply (default: fix out-of-date branches)
dependamerge merge https://github.com/myorg/repo1/pull/78 \
--threshold 0.9 --progressThe --force option provides tiered override levels for bypassing safety checks
when you have appropriate permissions.
# Bypass code owner review requirements (you are a code owner)
dependamerge merge https://github.com/myorg/repo1/pull/45 --force=code-owners
# Bypass branch protection validation (you have admin/bypass permissions)
dependamerge merge https://github.com/myorg/repo1/pull/67 --force=protection-rules
# Emergency override - attempt merge despite most warnings (use with caution)
dependamerge merge https://github.com/myorg/repo1/pull/89 --force=allForce Levels:
none(default): Respect all protectionscode-owners: Bypass code owner review requirementsprotection-rules: Bypass branch protection checks (requires permissions)all: Attempt merge despite most warnings (not recommended)
Dependamerge provides configurable safety levels to handle different repository protection scenarios:
none: Respect all protections and requirementscode-owners: Bypass code owner review requirements (default)protection-rules: Bypass branch protection checks (requires permissions)all: Attempt merge despite most warnings (not recommended)
The default code-owners level allows automated merging of dependency updates
even when repositories require code owner reviews, which is the most common
blocking scenario for automation PRs.
Examples:
# Use full safety (respect all protections)
dependamerge merge https://github.com/owner/repo/pull/123 --force=none
# Default behavior (bypass code owner requirements)
dependamerge merge https://github.com/owner/repo/pull/123
# Bypass branch protection rules (requires admin permissions)
dependamerge merge https://github.com/owner/repo/pull/123 \
--force=protection-rules
# Force merge despite most warnings (use with extreme caution)
dependamerge merge https://github.com/owner/repo/pull/123 --force=all- Mergeable Check: Verifies PRs are in a mergeable state before attempting merge
- Auto-Fix: Automatically update out-of-date branches by default
(use
--no-fixto disable) - Detailed Status: Shows specific reasons preventing PR merges (conflicts, blocked by checks, etc.)
- Similarity Threshold: Configurable confidence threshold prevents incorrect matches
- Interactive Mode by Default: Shows results then lets you choose to
proceed (use
--no-confirmto skip) - Detailed Logging: Shows which PRs match and why they match
- SHA-Based Validation: Provides unique SHA hash for security
- Author Isolation: When using SHA validation, processes PRs from the same author as source PR
- Commit Binding: SHA changes if commit message changes, preventing replay attacks
- Cross-Author Protection: When enabled, one author's SHA cannot work for another author's PRs
The tool now supports GitHub PR URLs with path segments:
# These URL formats now work:
dependamerge merge https://github.com/owner/repo/pull/123
dependamerge merge https://github.com/owner/repo/pull/123/
dependamerge merge https://github.com/owner/repo/pull/123/files
dependamerge merge https://github.com/owner/repo/pull/123/commits
dependamerge merge https://github.com/owner/repo/pull/123/files/diffThis enhancement allows you to copy URLs directly from GitHub's PR pages without worrying about the specific tab you're viewing.
The merge command also accepts repository and owner (organisation or
user) URLs, selecting the operation scope from the URL shape:
# Single PR
dependamerge merge https://github.com/owner/repo/pull/123
# Whole repository (all open automation PRs)
dependamerge merge https://github.com/owner/repo
dependamerge merge https://github.com/owner/repo/pulls
# Whole owner: every repository of an organisation or user
dependamerge merge https://github.com/owner
dependamerge merge https://github.com/owner/
dependamerge merge https://github.com/orgs/owner
dependamerge merge https://github.com/orgs/owner/repositories| URL shape | Scope |
|---|---|
.../owner/repo/pull/123 |
single PR |
.../owner/repo |
repository |
.../owner or .../orgs/owner |
owner-wide |
(If you already followed the Installation section, you can skip these repeated steps.)
git clone <repository-url>
cd dependamerge
uv venv .venv
source .venv/bin/activate
uv sync --group devThe dev dependency group mirrors the legacy .[dev] extra.
uv run pytestYou can pass args as usual:
uv run pytest -k "similarity and not slow" -vvLive integration tests (under tests/integration/) drive the real CLI in
--dry-run mode against GitHub and Gerrit, exercising every sub-command
(status, blocked, merge, close) against both organization and personal
accounts and across every supported owner-URL form. Pytest deselects them by
default; opt in via --run-integration (or DEPENDAMERGE_RUN_INTEGRATION=1).
Each test fails safe: it skips when its credentials or an open automation PR are
not available, so it never mutates a repository and never fails on an empty
target space.
# GitHub integration tests (needs a token; a token without write access works)
GITHUB_TOKEN=... uv run pytest tests/integration --run-integration --no-cov
# Point at different targets (defaults: org lfreleng-actions,
# user ModeSevenIndustrialSolutions)
DEPENDAMERGE_IT_ORG=my-org DEPENDAMERGE_IT_USER=my-user \
GITHUB_TOKEN=... uv run pytest tests/integration --run-integration --no-cov
# Gerrit integration test (skips unless the host and credentials are present)
DEPENDAMERGE_IT_GERRIT_HOST=gerrit.example.org \
DEPENDAMERGE_IT_GERRIT_BASE_PATH=r \
GERRIT_USERNAME=... GERRIT_PASSWORD=... \
uv run pytest tests/integration/test_live_gerrit.py --run-integration --no-covThe Integration Tests (dry-run) GitHub Actions workflow runs this suite on
every pull request with read-scoped permissions.
Tests are automatically integrated into pre-commit hooks and run on every commit. This project uses prek (a faster, Rust-based drop-in replacement for pre-commit) as the local hook runner:
# Install prek git hooks (tests will run automatically on commits)
prek install
# Run all checks including tests manually
prek run --all-files
# Run the pytest hook
prek run pytestNote: The pytest hook runs automatically on every commit to ensure code quality.
# Format (Black)
uv run black src tests
# Lint (Flake8 – still present)
uv run flake8 src tests
# Type checking
uv run mypy src
# (Optional) Ruff (if/when added)
# uv run ruff check .- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
Apache-2.0 License - see LICENSE file for details.
Error: GitHub token needed
Solution: Set GITHUB_TOKEN environment variable or use --token flag.
Failed to fetch organization repositories
Solution: Ensure your token has the required permissions:
- Classic tokens:
read:orgscope - Fine-grained tokens: "Organization members: Read access" permission
403 Forbidden during merge attempt
Solution: Ensure your token has write permissions:
- Classic tokens:
reposcope (orpublic_repofor public repositories) - Fine-grained tokens: "Contents: Read and write" permission
Failed to approve PR: Missing 'Pull requests: Read and write' permission
Solution: Ensure your token can create PR reviews:
- Classic tokens:
reposcope (includes PR review permissions) - Fine-grained tokens: "Pull requests: Read and write" permission
Failed to check PR status
Solution: Add workflow/actions permissions:
- Classic tokens:
workflowscope - Fine-grained tokens: "Workflows: Read and write" permission
- Check that other repositories have open automation PRs
- Try lowering the similarity threshold with
--threshold 0.7 - Use interactive mode (default) to see detailed matching information and optionally proceed with merge
- Ensure PRs are in mergeable state (no conflicts)
- Check that you have write permissions to the target repositories
- Verify the repository settings permit the merge method
❌ Gerrit credentials not found in environment.
Solution: Set the required environment variables:
export GERRIT_USERNAME="your_username"
export GERRIT_PASSWORD="your_http_password"Note: These are your HTTP credentials from Gerrit, not your SSO/LDAP password. Generate them in Gerrit under Settings → HTTP Credentials.
❌ Gerrit authentication failed
Solution:
- Verify your HTTP credentials are correct
- Check that you have permission to access the Gerrit server
- Ensure the server URL is correct and accessible
- Try testing with curl:
curl -u "$GERRIT_USERNAME:$GERRIT_PASSWORD" \
"https://gerrit.example.org/a/accounts/self"❌ Invalid URL: Cannot determine platform for URL
Solution: Ensure your Gerrit URL follows the correct format:
https://gerrit.example.org/c/project/name/+/12345https://gerrit.example.org/base/c/project/name/+/12345
The URL must contain /c/ and /+/ for the tool to recognize it as a Gerrit change.
- Check the command help (local dev):
uv run dependamerge --help - For PyPI usage:
uvx dependamerge --help - Enable verbose output with
--verboseor-v - Review similarity scoring in interactive mode (default behavior)
Dependamerge handles authentication tokens (GitHub PATs, Gerrit HTTP credentials) and applies the following layers of protection to prevent accidental exposure:
- Token Redaction — All git operations redact tokens from logs and
error messages. The
git_opsmodule recognises GitHub classic tokens (ghp_), fine-grained tokens (github_pat_), App installation tokens (ghs_), user-to-server tokens (ghu_), GitLab tokens (glpat-), basic-auth URLs, andx-access-tokenURLs - Safe Object Representation — All classes that store credentials
(
GitHubClient,GitHubAsync,AsyncMergeManager,AsyncCloseManager,GerritRestClient,GerritCredentials,NetrcCredentials) define__repr__methods that mask sensitive values - Log Hygiene — Credential values (tokens, passwords, or usernames) never appear in log output at any level. Debug logs record credential sources (e.g., "environment variables", ".netrc") but never the credential values themselves
- Scoped Debug Logging — The
--verboseflag enables DEBUG level logging for thedependamerge.*namespace; third-party libraries (includinghttpx, which logs request headers at TRACE level) remain at WARNING - Exception Sanitisation — Git command errors redact token patterns
from all stored attributes (
args_vec,stdout,stderr)
URL hostname checks use urlparse()-based exact matching via the
_host_matches() function, not substring checks. This prevents bypass
attacks where a crafted hostname (e.g., evil-github.com.attacker.net)
could fool a naïve substring check into trusting a malicious host.
- Store GitHub tokens securely (environment variables, not in code)
- Use tokens with minimal required permissions for your use case
- Rotate access tokens periodically
- Review PR changes in interactive preview mode first
- Be cautious with low similarity thresholds
- Consider using repository-specific tokens instead of organisation-wide access when possible
- Audit token permissions and revoke unused tokens periodically
- Store Gerrit HTTP credentials securely (environment variables, not in code)
- Use HTTP credentials generated specifically for API access, not your main password
- Regenerate HTTP credentials periodically in Gerrit Settings → HTTP Credentials
- Review changes in interactive preview mode before submitting
- Be aware that the tool performs +2 Code-Review and submit operations using your credentials
- Ensure you have appropriate permissions on the Gerrit server before running bulk operations