What Happens After You Submit Your First Pull Requests

Table of Contents

A few days ago I submitted 10 pull requests to 7 different open source repos. I’d never done a PR before that day. Today I checked back on all of them and learned that submitting is the easy part. What happens next is where the real lessons are.

The Scorecard

Out of 10 PRs:

That’s a 25% merge rate on decided PRs. Sounds low but it’s actually normal for someone doing rapid-fire first contributions. Here’s why the three got closed, and what each taught me.

Lesson 1: AI Detection Is Real

My first docs PR to distreqx (a JAX probability library) got one comment from the maintainer: “ai generated text.” Then he closed it.

I used Kiro to help write the content, and apparently it showed. The structured sections, the bullet points, the comprehensive feature tables. It read like a machine wrote it because, well, a machine helped write it.

This changed how I approach docs contributions now. If writing text for humans to read, I write it myself or at least rewrite it in my own voice before submitting. Tools can help with code. For prose, the human touch matters.

Lesson 2: Someone Might Beat You

My Foam-Agent fix (replacing an em dash that rendered as garbage on Windows) got closed because someone else submitted the exact same one-character change 14 hours earlier. The maintainer was friendly about it: “Thanks for the contribution. This is a correct fix! However, #20 was opened earlier with a byte-identical change.”

No hard feelings, but it’s wasted effort. Now I check for existing PRs before starting work.

Lesson 3: “Closed” Doesn’t Always Mean “Rejected”

The grok-mcp-server PR was the most interesting case. The maintainer loved the contribution. He gave detailed feedback, I applied some fixes, but the GitHub suggestion UI mangled the formatting. Rather than ask me to fix it again, he incorporated my FAQ directly into main and credited me as co-author in the commit.

My PR shows as “closed” but my name is in their git history. That counts.

Lesson 4: CI Failures Are Your Problem

My test PR to distreqx had all three CI runs failing. Not because the tests were wrong, but because I used jax.experimental.enable_x64() which their type checker (pyright) doesn’t recognize. The tests would have passed if run directly, but their pre-commit hooks caught a type error.

I fixed it by replacing the deprecated API with jax.config.update("jax_enable_x64", True). Pushed the fix, no comment needed. The PR updates automatically.

Lesson: run the project’s full linting/type-checking pipeline locally before pushing. Don’t rely on CI to tell you what you should have caught yourself.

Lesson 5: Most Small Repos Just Never Respond

Four of my PRs are still sitting there with zero activity after several days. The command-line-chess repo hasn’t had a commit since 2023. The sunfish maintainer hasn’t looked at new PRs in weeks.

This is normal. Not every maintainer checks their notifications. Some projects are effectively done but not archived. You learn to recognize the signs (old last commit, pile of unreviewed PRs) and choose more active repos next time.

Lesson 6: Formatting Matters More Than You Think

The distreqx type-hints PR got “needs formatting” as feedback. I’d written the code correctly but didn’t run Black (their formatter) before pushing. The function signatures wrapped differently than their codebase style.

One command (python -m black <file>) and a push fixed it. But it left a bad first impression.

New rule: always check for .pre-commit-config.yaml and run whatever formatters the project uses before committing.

What I Built Today (Internal Improvements)

Based on everything that went wrong, I built tools to prevent repeating mistakes:

I also found a Windows-specific bug in one of the repos I contributed to (7 tests fail because they use Unicode checkmarks without specifying UTF-8 encoding). Bookmarked that for next time.

My Updated Rules

After today’s lessons, here’s what I do differently:

  1. Run the full CI locally before pushing. Linters, type checkers, tests. All of it.
  2. Check for existing PRs before starting. Someone might already be working on it.
  3. Write PR descriptions in my own voice. Not structured AI-speak.
  4. Don’t spam one repo. Max 2 PRs per repo per session.
  5. Pick repos that recently merged external PRs. That proves the maintainer reviews things.
  6. Only work on things I can test on my machine. No more guessing if it works on macOS.

The Contribution That Felt Best

Today’s cleanest win: removing a dead method from readme2demo’s sandbox.py. Six lines deleted. Zero call sites confirmed via grep. All tests pass. Brief PR description. No drama.

That’s what a good contribution feels like. Small, obvious, verified, one thing. If every PR was like that, the merge rate would be much higher.

Next Steps

The first blog post was about “look, a beginner can do this.” This one is about “here’s what actually happens, and here’s how to get better at it.” The process is iterative. You submit, you learn, you adjust.


Part 2 of the open source contribution series. Part 1: I Built an Open Source Contribution Toolkit in 57 Tokens.