GitHub And Open Source Collaboration
Open Source Contribution Path
Most rejected first-time pull requests aren't rejected for bad code — they're rejected because the contributor skipped a step that would have told them the maintainer didn't want that change, in that shape, at all. This lesson covers the path from "I want to contribute" to a merged pull request, and the etiquette that makes a maintainer want to work with you again.
Finding Something To Work On
- Labels meant for newcomers —
good first issueandhelp wantedare the closest thing to an explicit invitation; a maintainer tagged that issue as scoped and approachable for someone new to the codebase. - Documentation gaps — a confusing install step, a missing example, an outdated code snippet — are lower-risk first contributions than logic changes: smaller diffs, easier to review, and the contributor doesn't need deep familiarity with the codebase's internals to get it right.
- A bug you hit yourself while using the project — you already have a reproduction case and a concrete understanding of the problem, which is most of the work of a good bug report already done.
- What NOT to start with: a large refactor, a new major feature, or "I rewrote this in a style I prefer" — all high-effort, high-risk-of-rejection first contributions, because they require the maintainer to evaluate a large diff against project direction they haven't discussed with you yet.
Read Before You Write
Before opening an issue or PR, check for a CONTRIBUTING.md file — many projects document exactly how they want contributions made: coding style, test requirements, commit message format, whether a Contributor License Agreement (CLA) or Developer Certificate of Origin (DCO) sign-off is required. Skipping this is the single most avoidable cause of a frustrating first contribution — the rules were often written down precisely because the maintainer got tired of explaining them in every PR review.
Also check open and recently closed issues/PRs for the same problem — someone may have already reported it, fixed it, or explained why it's not a bug. Duplicating effort the project has already resolved is a common, easily-avoided first mistake.
Discuss Before You Build (For Anything Nontrivial)
For a typo fix or small doc correction, just send the PR. For anything larger — a new feature, a behavior change, a nontrivial refactor — open an issue first and describe what you want to do before writing the code. This is not bureaucracy; it's the step that prevents wasted work. A maintainer might already have a different design in mind, might have rejected this exact idea before for a reason not visible from outside, or might simply not want the added maintenance surface. Finding that out before you've written 400 lines is much better for both of you than after.
The Standard Workflow
- Fork the repository to your own account (or, if you have write access, create a branch directly).
- Branch from the project's default branch, named descriptively.
- Make the smallest change that solves the discussed problem. Resist the urge to also fix unrelated things you noticed along the way — a focused diff is faster to review and less likely to be rejected for scope creep; file a separate issue for the unrelated problem instead.
- Match the project's existing style and conventions — indentation, naming, test structure — even if you'd personally do it differently. Consistency with the existing codebase matters more than your personal preference in someone else's project.
- Add or update tests covering the change, following the project's existing test patterns.
- Write a clear PR description: what changed, why, and a link to the issue discussion if one exists.
- Respond to review promptly and without defensiveness. Maintainer feedback on a first PR is usually about fit with the project's conventions, not a judgment of your ability — treat requested changes as normal, not as a sign the contribution was unwelcome.
Licensing And Legal Signals
Every contribution you send becomes part of a codebase under that project's license — understand what you're agreeing to. Some projects require a CLA (a separate legal agreement) or DCO sign-off (git commit -s, certifying you wrote the code and have the right to submit it under the project's license) before accepting contributions; check CONTRIBUTING.md for this requirement before your PR is blocked on it late. Never submit code you copied from a differently-licensed source without checking compatibility — this is the contributor-side mirror of the license-evaluation care covered when consuming dependencies.
What Makes A First Contribution Get Merged
- Scope matches what was discussed — no surprise extra changes bundled in.
- Tests exist and pass, following the project's own conventions for how tests are written.
- The diff is readable — a reviewer should be able to understand what changed and why from the diff and description alone, without needing a call to explain it.
- Response to feedback is fast and non-defensive — a maintainer reviewing volunteer contributions in their spare time is far more likely to keep engaging with a contributor who responds promptly and adjusts, versus one who argues every point or goes silent for weeks.
Failure Modes
The most common failure is a large, unrequested rewrite as a first contribution — sent with good intentions, but forcing the maintainer to evaluate an unplanned, high-risk change against project direction never discussed, which is why it's rejected regardless of code quality.
The second is skipping CONTRIBUTING.md and getting the basics wrong — wrong branch, missing tests, wrong commit format — creating review friction that has nothing to do with the substance of the change and everything to do with skippable process.
The third is taking review feedback personally and disengaging — going quiet or arguing defensively after requested changes, which (from the maintainer's side) looks identical to abandoning the contribution, and often ends the same way: the PR goes stale and gets closed.
The fourth is not checking for duplicate or prior-rejected work, resubmitting something the project already declined, without engaging with the reason it was declined the first time.
Review Checklist
- The contribution's scope matches what was discussed in an issue (for anything beyond a trivial fix), with no unrelated changes bundled in.
CONTRIBUTING.mdconventions (style, tests, commit format, CLA/DCO) were checked and followed before the PR was opened.- Tests exist for the change and follow the project's own test patterns.
- The PR description explains what and why clearly enough that a reviewer doesn't need external context.
- Prior issues/PRs were checked to avoid duplicating already-resolved or already-declined work.
- The contributor's response plan to review feedback is prompt engagement, not silence or defensiveness.
What You Should Be Able To Do
After this lesson, you should be able to find an appropriately-scoped first issue, read and follow a project's contribution conventions, discuss a nontrivial change before building it, submit a focused pull request with tests, and respond to maintainer feedback in a way that keeps the collaboration working rather than ending it.
Practice
Plan a first contribution
You use a PHP validation library daily and noticed its README example for custom validators is outdated — it references a method (addRule()) that was renamed to registerRule() two major versions ago, so anyone copying the example gets a fatal error. You want to fix it and this would be your first contribution to this project.
Write a contribution plan covering:
- whether this needs a discussion issue first, or can go straight to a PR, and why;
- what you'd check before opening anything (two specific things);
- the shape of the PR itself: what files change, whether tests are needed, what the description says;
- what you'd do if, three days after opening the PR, there's been no maintainer response.
Show solution
Contribution Plan
Discussion issue first, or straight to PR? Straight to PR. This is a small, unambiguous documentation correction — the old method name is objectively wrong (it causes a fatal error if followed), there's no design decision to discuss, and no reasonable maintainer would want to negotiate whether a broken example should be fixed. The article's guidance to discuss first applies to changes where the maintainer might have a different design in mind or might not want the change at all; neither applies here.
Two things to check before opening anything: (1) search open and recently closed issues/PRs for "addRule" or "registerRule" to confirm nobody has already reported or fixed this — duplicating already-done work is an easy, avoidable mistake; (2) check CONTRIBUTING.md for any documentation-specific conventions (a docs folder separate from the README, a required PR template, DCO sign-off) so the PR doesn't get bounced for a process reason unrelated to the actual fix.
Shape of the PR: one file changes — the README (or wherever the example lives) — updating addRule() to registerRule() in the code sample and, if useful, a one-line note that this changed in the relevant major version for anyone still on the older API. No tests are needed; this is documentation, not code — the article's guidance to add tests applies to logic changes, and forcing a test requirement onto a doc fix would be scope creep in the other direction. The PR description states plainly: "The custom validator example uses addRule(), which was renamed to registerRule() in vX. Anyone copying this example currently hits a fatal error. Updated to the current method name." That's enough context for a reviewer to approve without needing to ask what changed or why.
No response after three days: nothing, yet. Three days is well within normal response time for a volunteer-maintained project — the article's point about recognizing volunteer maintainer constraints applies directly here. Treating slow response as rejection and either escalating aggressively or abandoning the PR would be an overreaction. A reasonable next step, if there's still no response after a longer window (a couple of weeks, adjusted for how active the project generally is based on its recent history), is a single polite follow-up comment on the PR — not a new issue, not pinging the maintainer elsewhere, just a low-pressure nudge on the existing thread.
Diagnose a rejected PR
Diagnose what went wrong and write a plan covering:
- the first thing to look at to understand the actual scope of what was submitted versus what was needed;
- the false assumption the contributor made;
- how the contributor should respond to this specific rejection (not "what should they have done differently before" — what do they do now);
- the durable habit that prevents this next time.
Show solution
Diagnosis
First thing to check: diff the PR against what the original bug actually required — how many lines fix the reported bug versus how many are the style pass and API changes. This immediately shows the scope mismatch in concrete terms: if the bug fix is 5 lines and the PR is 400, that ratio alone explains why the maintainer can't review it "as-is" — the actual fix is buried inside changes nobody asked for or discussed.
The false assumption: the contributor assumed that noticing an improvement while working in the code was sufficient justification to make that change unilaterally, without checking whether the maintainer agreed the API signatures were worth changing or the style was worth reformatting. This is exactly the article's warning about bundling unrelated changes — each individual change might even be reasonable on its own, but presenting all three together, undiscussed, forces the maintainer to evaluate a design decision (the API changes) and a low-value diff-noise problem (the style pass) just to get the one thing that was actually needed reviewed.
How to respond now: don't argue that the extra changes were good ideas — that treats the maintainer's clear, specific feedback as a debate to win rather than direction to follow, which is the "defensive" failure mode the article calls out. The right response is to close the PR (or the maintainer already has) and open a new one containing only the original bug fix, referencing the closed PR for context if useful. If the contributor still believes the API changes have merit, that's a separate conversation — open an issue proposing them on their own, after the bug fix has landed, so the maintainer can evaluate that idea without it being tangled up in an unrelated fix.
The durable habit: submit one logical change per PR. When something else looks worth improving while working on an unrelated fix, write it down (a new issue, or even just a personal note) instead of including it in the current diff. This is the direct fix for the failure mode here — it doesn't require better judgment about which improvements are "good enough" to include, it just removes the bundling entirely, which is what actually caused the rejection.
Write a CONTRIBUTING.md
You maintain a small PHP library (a CSV parsing utility) and have started getting occasional pull requests, but each one arrives with a different code style, no tests, and often bundled with unrelated cleanup. You want a CONTRIBUTING.md that heads off the friction this lesson's article describes, without being so long that nobody reads it.
Write a CONTRIBUTING.md covering:
- when to open an issue before a PR, versus when to just send the PR;
- the scope rule (one logical change per PR);
- the specific test expectation;
- code style (point at an automated tool rather than prose rules, if applicable);
- how you'll respond to contributors and what response time they should expect.
Keep it under roughly 300 words — a guide nobody reads because it's too long defeats its own purpose.
Show solution
Before you start
- Bug fix or typo? Just send a PR.
- New feature or behavior change? Open an issue first describing what you want to do. This saves you from building something that doesn't fit the project's direction — I'll respond within a few days.
- Check open/closed issues and PRs first — your idea may already be reported, fixed, or discussed.
Scope
One logical change per PR. If you notice something else worth fixing while you're in there, that's a separate issue or PR, not part of this one. A focused diff gets reviewed and merged much faster than a bundled one.
Tests
Every behavior change needs a test in tests/, following the existing
PHPUnit structure in that directory. A PR without a test for new behavior
will get a review comment asking for one before merge.
Style
Run composer cs-fix before opening your PR — it applies this project's
PHP-CS-Fixer config automatically. Don't hand-format to match your own
preference; let the tool handle it so style is never a review discussion.
What to expect from me
I maintain this in my spare time. I aim to respond within a week, longer around holidays — a bump comment after two weeks is welcome and won't be seen as pushy. I'll say clearly if something doesn't fit rather than leaving a PR open indefinitely.
License
By submitting a PR, you agree your contribution is licensed under this project's MIT license.
This covers exactly the five things the exercise asked for, each as a short, actionable rule rather than an essay: when to discuss first, the one-change-per-PR scope rule, a concrete test requirement tied to the actual test directory, an automated style tool instead of prose formatting rules (removing style as a subjective review point entirely), and a stated response-time expectation that heads off the "silence means rejection" misunderstanding the article warns about. Pointing at `composer cs-fix` instead of writing out style rules is deliberate — it turns a discussion into a command a contributor can run themselves before ever opening the PR.