You’ve Been Using Their Software for Free. Time to Give Something Back.
Not a guilt trip — just context. That Compose plugin you use every day, the CLI tool you couldn’t live without, the library that saved you three weeks of work — all of it was written by people who put in their own time to build something useful and share it. Some of them are paid to do it. Many aren’t.
Contributing back isn’t just altruism (though it is that too). It’s how you learn to write production-quality code faster than any tutorial, build a portfolio that actually impresses engineers, and get your name in release notes for software used by thousands of people.
Here’s the thing: most maintainers are not waiting to judge you. They’re waiting for someone to fix that bug so they don’t have to.
Finding Good First Issues
The mistake most people make: trying to fix a complex architectural problem in a codebase they’ve never read. Start smaller.
Use the labels
GitHub issues labeled good first issue, beginner-friendly, help wanted, or easy are explicitly tagged by maintainers as approachable. Filter by these labels:
https://github.com/search?q=label%3A%22good+first+issue%22+state%3Aopen&type=Issues
Sites like goodfirstissue.dev and up-for-grabs.net aggregate these across repositories.
What makes a good starter issue
- Documentation fixes (typos, outdated examples, missing explanations)
- Small bug fixes where the bug is clearly described and reproducible
- Adding a test for an untested function
- Updating a dependency version
- Adding a missing error message
What’s NOT a good starter issue:
- “Rewrite the auth system to be more modular”
- Anything that requires deep knowledge of internal architecture
- Issues labeled “RFC” or “design discussion” — those are deliberation spaces, not task queues
Comment before you code
Found a good first issue? Leave a comment: “I’d like to work on this. Is it still open and is my approach X correct?” Maintainers appreciate the check-in. It prevents two people working on the same thing and ensures you’re not solving the wrong problem.
The Fork Workflow
Here’s the correct sequence. Don’t skip steps.
# 1. Fork on GitHub (click the Fork button)
# 2. Clone YOUR fork, not the original
git clone https://github.com/YOURUSERNAME/project-name.git
cd project-name
# 3. Add the original as upstream
git remote add upstream https://github.com/ORIGINALOWNER/project-name.git
# 4. Create a branch for your change
git checkout -b fix/login-null-pointer-crash
# Branch name convention: fix/<description>, feat/<description>, docs/<description>
# 5. Make your changes, then stage and commit
git add src/auth/login.py
git commit -m "fix: handle null user object in login handler"
# 6. Before opening a PR, sync with upstream
git fetch upstream
git rebase upstream/main
# Resolve conflicts if any
# 7. Push to YOUR fork
git push origin fix/login-null-pointer-crash
# 8. Open a PR from your fork's branch to upstream main
Why rebase before opening a PR? Because if upstream has moved forward since you forked, your branch may conflict with recent changes. Rebasing puts your commits on top of the latest upstream — a cleaner history and fewer merge conflicts for the maintainer.
Commit Message Conventions
Most projects follow Conventional Commits or similar:
type(scope): short description
Longer explanation if needed. What changed and why.
Closes #123
Types:
fix:— bug fixfeat:— new featuredocs:— documentation onlytest:— adding or fixing testsrefactor:— code change that doesn’t add features or fix bugschore:— dependency updates, build changes
Example:
fix(auth): handle null user object in login handler
When the session store returns null for an expired session,
the login handler was throwing a NullPointerException instead
of redirecting to the login page. Added null check and redirect.
Closes #456
Check the project’s CONTRIBUTING.md for their specific conventions. Always. Some projects use emoji prefixes. Some want present tense. Some want past tense. Read before you write.
DCO and CLA: What You’re Agreeing To
Many projects require one of:
DCO (Developer Certificate of Origin): You certify that you have the right to submit the code (you wrote it, it’s not someone else’s proprietary code). Sign off by adding -s to your commit:
git commit -s -m "fix: your message here"
# Adds "Signed-off-by: Your Name <email>" to commit
CLA (Contributor License Agreement): A legal agreement (usually a click-through form) transferring or licensing your code contribution to the project. Common in corporate-backed projects (Microsoft, Google, etc.). A bot will usually comment on your PR with a link to sign it.
Neither is scary. Read them. Sign/agree when required. It’s housekeeping, not a trap.
Writing a PR Description That Gets Reviewed Faster
A PR description is a cover letter for your code. Maintainers review dozens of PRs. The ones with clear context get reviewed first.
Good PR description:
## What this changes
Fixes a NullPointerException when a user's session has expired and they
attempt to log in. Previously the server returned 500; now it redirects
to /login with an appropriate message.
## Why this was broken
The `getSession()` method returns `null` for expired sessions, but the
login handler assumed it always returned a valid object.
## Testing
- Added unit test: `test_null_session_redirects_to_login`
- Manually tested: logged out, expired session manually, confirmed redirect
Closes #456
What NOT to do in a PR description:
- Leave it blank
- Write “Fixed the bug”
- Describe every line of code you changed (that’s what the diff is for)
Responding to Review Feedback
The maintainer left comments. Your PR didn’t merge instantly. This is normal — it’s not a rejection.
Do:
- Respond to every comment, even with just “Fixed” or “Done”
- Push new commits to the same branch (the PR updates automatically)
- Ask clarifying questions if a review comment is unclear
- Thank reviewers for their time (it’s a human being spending their time helping you)
Don’t:
- Argue about style preferences (it’s their project, their style)
- Push a force-push that rewrites history during review — it makes comparing changes confusing
- Go silent for weeks — if you can’t continue, leave a comment saying so
After making changes:
git add .
git commit -m "address review feedback: extract null check to helper"
git push origin fix/login-null-pointer-crash
Leave a comment: “Updated to address feedback — extracted null check to validateSession() helper per your suggestion.”
What NOT to Do
Learning from others’ mistakes is faster:
- Unsolicited refactors: Don’t open a PR that “also cleans up some other stuff while I was in here.” One PR, one change. If you see other things to fix, open separate issues.
- Huge scope creep: The issue says “fix the typo in the README.” Don’t also rewrite the README.
- Entitled attitude: Maintainers are volunteers. If your PR sits for two weeks, politely bump it once. Don’t escalate.
- Ignoring CI failures: If tests fail on your PR, fix them before asking for review.
- Submitting untested code: Run the test suite locally before pushing. All of it.
Staying Engaged After Merge
Your PR merged. That’s a real thing that happened. Congrats.
Now:
- Watch the issue/PR — sometimes follow-up questions or regressions come up
- Check the next release notes — your name might appear under Contributors
- Consider what else in the project interests you
The first contribution is the hardest. After that, you know the codebase, you know the maintainer’s preferences, and you know the workflow. The second contribution takes a third of the time.
Some of the most prolific open source contributors started with a typo fix.