willitmerge
Before you spend a weekend on a pull request, check whether that repository has ever merged a stranger's.
Stars, recent commits and a friendly CONTRIBUTING.md tell you nothing about it. Plenty of busy,
well starred projects have not merged an outside contribution in a year. willitmerge reads the
one record that does answer the question: what has actually happened to pull requests opened by
people who are not on the team.
$ willitmerge pallets/flask psf/requests PrefectHQ/prefect astral-sh/ruff pydantic/pydantic
repository verdict merged rate median p90 waiting
----------------- -------- ------- ---- ------ --- --------------------
pallets/flask UNLIKELY 2/116 2% 3w 4w -
psf/requests UNLIKELY 21/228 9% 6h 9d 16 open, oldest 155d
PrefectHQ/prefect MIXED 158/287 55% 24h 8d 34 open, oldest 61d
astral-sh/ruff LIKELY 451/624 72% 11h 6d 155 open, oldest 76d
pydantic/pydantic UNLIKELY 92/354 26% 22h 9d 20 open, oldest 177d
Real output, measured on 2026-08-25 over the preceding 180 days. Flask closed 114 pull requests from outside the team in that window and merged 2. Ruff merged 451 of 624. Both are busy, popular, well maintained projects, and the difference between them is not visible from anything on their front pages.
Install
pip install git+https://github.com/muhzuhaib/willitmerge
No runtime dependencies. Python 3.10 or newer.
The PyPI release is set up but not yet published, so pip install willitmerge
does not work today. Installing from the tag above gives exactly the same code.
Use
willitmerge OWNER/REPO [OWNER/REPO ...] # last 180 days
willitmerge django/django --days 365 # a longer window
willitmerge pallets/flask --json # for scripts
GitHub allows 60 unauthenticated requests an hour, which one large repository can spend on its own.
willitmerge picks a token up automatically from GITHUB_TOKEN, from GH_TOKEN, or from the
GitHub CLI if you are signed in with gh auth login. It only ever reads public pull request data.
What the columns mean
| Column | Meaning |
|---|---|
verdict |
LIKELY, MIXED, UNLIKELY, or TOO FEW when there is not enough history to say |
merged |
merged, out of the pull requests that were decided (merged or closed unmerged) |
rate |
the share of decided outsider pull requests that were merged |
median |
typical time from opening to merge, merged ones only |
p90 |
the slow tail: one outsider pull request in ten waited at least this long |
waiting |
outsider pull requests still open, and how many have been open over 30 days |
A verdict needs at least five decided pull requests from outside the team. Below that the tool
prints TOO FEW instead of a percentage, because a merge rate over two samples is one person's
luck rather than a repository's habit.
Design decisions
The merge rate is the headline, not the merge speed. The obvious version of this tool measures how long merged pull requests took, and that measurement has survivorship bias baked into it. A repository that merges one outsider in ten, within an hour, scores better on latency alone than a repository that merges nine in ten within a week. The first of those will waste your weekend. So every summary reports how many outsider pull requests were decided and what share of them got in, and the latency is read underneath that number rather than instead of it.
Open pull requests are undecided, and are counted separately. Treating an open pull request as
a rejection would mean the merge rate drops every time somebody opens a new one, which measures
popularity rather than receptiveness. But an outsider pull request that has sat untouched for four
months is real evidence and would vanish entirely if only closed ones were read. The waiting
column carries it, including the age of the oldest.
Bot pull requests are excluded, and that is load bearing. Dependabot and Renovate open pull requests that GitHub labels with an outsider association and that merge automatically in minutes. On any repository that runs one they are the majority of outsider pull requests, and leaving them in roughly halves the reported median. The test suite asserts the difference, so removing the filter fails the build rather than quietly changing every published number.
Pull requests are fetched sorted by creation date, not by update. Sorting by update, which is the API default, interleaves a pull request from three years ago that received a comment this morning with the ones opened this week, so there is no page at which it is safe to stop reading. Sorting by creation makes the stop condition exact: read until a pull request is older than the window, then stop.
p90 rather than the maximum. The worst case in any large repository is somebody's abandoned draft and tells you nothing. The point where one pull request in ten is still waiting is the number a contributor is actually risking.
No runtime dependencies. This is a command a person installs to answer one question before
deciding whether to start work. Every dependency is another way for that install to fail on
somebody's machine, and the standard library covers all of it. certifi is used if it happens to
already be installed, which helps on Windows, and is not required.
Limitations, stated plainly
author_associationis evaluated when the API is read, not when the pull request was opened. A contributor who has since joined the organisation reads asMEMBERon their old pull requests, so they drop out of the sample. This biases the result slightly pessimistic: it counts the people who contributed and stayed outsiders, not the ones who were invited in.- A bot with an ordinary user account is not detectable. The filter catches accounts GitHub
types as
Botand logins ending in[bot], which covers Dependabot, Renovate and GitHub Apps generally, but not a maintainer's own automation running under a normal account. - Projects that ask for an issue before a pull request will look quiet, and that is a fair description of what it takes to contribute there rather than a fault in the project.
- This is history, not a forecast. It reports what happened to other people. Maintainers change, and a good patch to an unresponsive repository is still a good patch.
Development
git clone https://github.com/muhzuhaib/willitmerge
cd willitmerge
pip install -e ".[dev]"
pytest -q
The tests never touch the network. tests/conftest.py builds pull request payloads with the same
fields the real endpoint returns, and the API client takes an opener so the rate limit, the 404
and the pagination stop condition are all exercised directly.
License
MIT. See LICENSE.
Metadata
Release files for willitmerge 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| willitmerge-0.1.0.tar.gz | 21.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| willitmerge-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.4 kB
Release files / willitmerge-0.1.0.tar.gz
| Download URL | willitmerge-0.1.0.tar.gz |
|---|---|
| Size | 21.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
75c04ba88fc8743082bc82e0b9021f4415acb72e3a936ebd7799e3bedd99ebd7
|
|
BLAKE2b-256 checksum How to use checksums |
e9e4a1ef9fc5d0d22325a614730ae9dee269d25f63ae9263438a28ce91a8d9f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency logRelease files / willitmerge-0.1.0-py3-none-any.whl
| Download URL | willitmerge-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e2dde5358dd5f624b9c2b36cd32b9cfccb3bfc2ec4f65f0b233db96fed5632f3
|
|
BLAKE2b-256 checksum How to use checksums |
cd5cacc6059fee87ba02e1705bb4d960de685fe716ea73534358a10c586dc6d9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency log