Most of My Pull Requests Started as an Annoyance
Drive-by fixes in qBittorrent, Dokploy and django-hijack: which ones merged, which didn't, and what the rejections taught me about scope.
My open-source contributions mostly start the same way. I use a piece of software, something about it bugs me, I go and read why, and sometimes the why is fixable.
That gets a good merge rate for small things and a bad one for anything ambitious. This is the tally from three projects.
qBittorrent: eight merged, several closed
I use qBittorrent on a Mac, and the macOS build had small, visible rough edges. Those fixes merged: text cut off in the About dialog, dark corner artifacts on line edits, delete shortcuts that didn't match platform conventions, invisible toolbar spacers replaced with visible separators, overlapping text in the priority editor, a background mismatch in the Add New Torrent dialog. Two later ones merged too: the RSS settings warning and the disabled speed graphs warning are now clickable.
Then I got ambitious. The options dialog says interface changes need a restart, and I set out to make theme settings apply at runtime: refresh icons, repaint cached widgets, keep the layout aligned. I spent days on it in whatever time I had after work, covering edge case after edge case. One maintainer's review found real regressions. Another asked a simple question: isn't this too much burden for such a minor goal?
It was. An occasional restart is a small cost to the user, and a pile of new signal plumbing in a codebase that other people maintain for free is a big cost to them. The PR was closed, which was the right call.
Another PR I opened described a desktop menu that, as a maintainer pointed out, doesn't exist. He was right and it was closed, and now I check my own PR descriptions as carefully as the diff.
Dokploy: a queue that lost deployments
Dokploy is a self-hosted deployment platform I use for some projects. Queued deployments could get stuck in a state the history view didn't show, so they were effectively invisible. My fix adds the missing state and shows queued deployments properly. At the time of writing the PR is still open. Plenty of good fixes sit for a while; maintainers have more PRs than hours.
django-hijack: a user that went stale mid-request
This one came from reading code rather than from a bug I hit. django-hijack's middleware copied request.user too early and could hold on to a stale lazy user object for the rest of the request. That broke a flow in allauth's headless mode, where the session and user cache are reset partway through a request, and the request kept seeing the old anonymous user. The fix re-copies the user lazily and adds a regression test for that reset flow without pulling allauth in as a test dependency, and it merged.
Scope
Small fixes that are obviously right get merged. With misaligned text, a wrong shortcut or a stale object, the maintainer can see the problem and the fix in a minute. Ambitious, optional changes usually don't get merged, and I think that's correct: every merged line is a line someone else maintains, and when the benefit is minor the maintenance cost outweighs it.
An open PR hasn't been rejected, either. Some of my best fixes are sitting in queues, which is normal, and chasing maintainers about it costs them the time you're asking for.
If you want to start, find the thing that annoyed you today, check whether someone already owns it, and keep the first PR small enough to review over a cup of tea. Most of what I know about scope came from the ones that weren't.