Merge-Pulls
Automate your pull request merging process with key featues below
- Multi-Repository Support (Process PRs across accessible repositories, and organizations(1))
- Filtering Capabilities (Filter PRs by base branch, ex/include labels(2), title prefix, and repo owner)
- Merge Readiness Evaluation (Check CI status, and code review approvals before merging)
- Flexible Merge Methods (Support merge, rebase, and squash (3))
- Bypass Option (Bypass required review count (4))
- Dry-Run Mode (Preview which PRs would be merged without performing the actual merge)
Note
- Multiple organizations access requires Classic Personal Access Token.
- In filtering PRs,
exclude-labelsis applied first, followed byinclude-labels.- Review repository | settings | pull requests on allowed PR merge strategies.
- The token owner must be allowed to bypass rule to merge PR.
📋 Prerequisites
Set up a GitHub personal access token (PAT) with the required permissions.
| Token Type | Required Permissions | Notes |
|---|---|---|
| Classic PAT | repo scope (full) |
Supports multi-organization access |
| Fine-grained PAT | Repository: Read & Write on Contents and Pull Requests |
Limited to single organization access |
Note
- If you are using GitHub Actions, the default
GITHUB_TOKENlacks the admin permissions needed to read branch protection settings.- GitHub Apps do not support GitHub REST API endpoints /users and /user/repos. Thus, we only support the use of classic and fine-grained perosnal access token.
🔧 Configuration Options
| Option | Description | Default |
|---|---|---|
base-branch |
merge the head branch to the base branch | main |
bypass-review-count |
bypass required review count rule | false |
dry-run |
preview (true); merge (false) | true |
exclude-labels |
filter out PRs from processing (comma/space seprated) | "" |
include-labels |
filter in PRs to process (comma/space seprated) | "" |
merge-method |
merge strategy: merge, rebase, or squash | merge |
owner |
filter repos to specific user/org | "" |
prefix |
filter PRs with title prefix | "" |
repo-type |
filter repos type from all, private, or public | all |
👥 Usage For GitHub Actions Users
Use this tool as a GitHub Action in your workflow file. An example workflow below:
- Runs
on scheduleat3:30 AM UTC (Monday-Friday)oron demand. - Configures
merge-pullsto:bypass-review-count- bypass required review count.dry-run- perform actual merge.exclude-labels- filter out PRs withstaleortestlabels.include-labels- filter in PRs withdependencieslabels.- use default values for the rest of the options.
---
name: merge-pulls
on:
schedule:
- cron: "30 3 * * 1-5"
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
merge-pulls:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Run merge-pulls # https://github.com/marketplace/actions/merge-pulls
uses: tagdots/merge-pulls@<commit sha> # <version>
env:
GH_TOKEN: ${{ secrets.SECRET_GITHUB_PAT }}
with:
# override default
bypass-review-count: true
dry-run: false
exclude-labels: "stale,test"
include-labels: "dependencies"
# # defaults
# base-branch: "main"
# merge-method: "merge"
# owner: ""
# prefix: ""
# repo-type: "all"
👨💻 Usage For CLI Users
Use this as CLI tool in a Python virtual environment. An example below:
- Installs
merge-pulls. - Exports
GH_TOKENenvironment variable (classic PAT). - Runs
merge-pullson pull requests that hasdependenciesormerge-readylabel. - Merges 4 of 6 open pull requests.
1. ~/work/<your project> $ uv pip install -U merge-pulls
2. ~/work/<your project> $ export GH_TOKEN="ghp_xxxxxxxxxxxxx"
3. ~/work/<your project> $ merge-pulls --include-labels "merge-ready,dependencies" --dry-run false
🚀 Starting Merge-Pulls (1.0.0)
📚 Loading configuration from: ./config/default.yaml
📚 Configuration (merged YAML and CLI):
base-branch: main
bypass-review-count: False
dry-run: False
exclude-labels: set()
include-labels: { 'dependencies', 'merge-ready' }
merge-method: merge
owner:
prefix:
repo-type: all
✅ Token Owner User Information :: login = Jack Nolan, Org. Access = ['org1', 'org2']
✅ Finding Open Pull Request...
▪ PR: https://github.com/org1/helloworld/pulls/101 (title: [GITHUB-ACTIONS] Bump the github-actions group with 7 updates)
▪ PR: https://github.com/org1/dotfiles/pulls/34 (title: [UV] Bump the uv group with 2 updates)
▪ PR: https://github.com/org1/dotfiles/pulls/35 (title: fix: memory leak caused by loop)
▪ PR: https://github.com/org2/rainer/pulls/21 (title: feat: add new CLI option)
▪ PR: https://github.com/org2/tac/pulls/2 (title: [PIP] Bump the pip group with 1 updates)
▪ PR: https://github.com/org2/tac/pulls/3 (title: refactor: generator expression)
Total Number of Open PR :: 6
✅ Finding PR Ready For Merge...
▪ Repo: org1/dotfiles (PR #34) -> Mergeable: True, Rebaseable: True, CI status checks: ok-for-merge, Approval Review checks: ok-for-merge
▪ Repo: org1/dotfiles (PR #35) -> Mergeable: True, Rebaseable: True, CI status checks: ok-for-merge, Approval Review checks: ok-for-merge
▪ Repo: org2/rainer (PR #21) -> Mergeable: True, Rebaseable: True, CI status checks: ok-for-merge, Approval Review checks: ok-for-merge
▪ Repo: org2/tac (PR #2) -> Mergeable: True, Rebaseable: False, CI status checks: ok-for-merge, Approval Review checks: ok-for-merge
Total Number of Mergeable PR :: 4
✅ Final Merged Open PR Info...
▪ PR: https://github.com/org1/dotfiles/pulls/34 (title: [UV] Bump the uv group with 2 updates)
▪ PR: https://github.com/org1/dotfiles/pulls/35 (title: fix: memory leak caused by loop)
▪ PR: https://github.com/org2/rainer/pulls/21 (title: feat: add new CLI option)
▪ PR: https://github.com/org2/tac/pulls/2 (title: [PIP] Bump the pip group with 1 updates)
Total Number of Merged PR :: 4
🎉 Merge-Pulls Summary :: {'open-prs': 6, 'mergeable-prs': 4, 'merged-prs': 4}
😕 Troubleshooting
Open an issue
Contributing
See Contributing
License
This project is licensed under the MIT License - see the LICENSE file for details.
🙌 Appreciation
If you find this project helpful, please ⭐ star it. Thank you.
References
User access token by GitHub App => 403
Metadata
Release files for merge-pulls 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| merge_pulls-1.0.1.tar.gz | 118.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| merge_pulls-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 142.8 kB
Release files / merge_pulls-1.0.1.tar.gz
| Download URL | merge_pulls-1.0.1.tar.gz |
|---|---|
| Size | 118.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
42d254fcbcd5e761d5c845be6cd8bd684da13d358992061d22d627ee7900f881
|
|
BLAKE2b-256 checksum How to use checksums |
bc259369b8ef69ef5fd1ef60f79e45bc676844398da6bdb24ca86d096b44ac51
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / merge_pulls-1.0.1-py3-none-any.whl
| Download URL | merge_pulls-1.0.1-py3-none-any.whl |
|---|---|
| Size | 24.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
79115a16aa1d9d295ecf75b1457942b76863101753fa0cac633ce42e42d770f5
|
|
BLAKE2b-256 checksum How to use checksums |
26a931e342fe81321cdd746a69c3aaa25492b36567ba30776b321a6fa323f3a6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|