15 - Your First Contribution¶
What this session is¶
The whole thing. Maybe two sessions. We walk through making a real contribution to a real Java OSS project end to end: fork, branch, change, test, push, PR, review, merge.
When the PR merges, you'll be an open-source contributor - a small, real one.
The workflow at a glance¶
- Fork on GitHub.
- Clone your fork.
- Add upstream as a remote.
- Branch off main.
- Set up dev environment, including any project-specific tools.
- Change the code; add a test.
- Run tests + checks locally (same commands as CI).
- Push to your fork; open the PR.
Takes 30 minutes the first time; 5 minutes once automatic.
Step 1: Fork¶
GitHub page → Fork (top right). Creates github.com/<you>/<project>.
Step 2: Clone¶
Step 3: Add upstream¶
You should see origin (your fork) and upstream (the real project).
Later, to pull updates from upstream:
Step 4: Branch¶
Hint at the change. Follow the project's branch-name convention if any.
Step 5: Set up the dev environment¶
Follow CONTRIBUTING.md. Usually:
Confirms tests pass on fresh clone. If not, stop and figure out why before changing anything - your "fix" might rest on a baseline that's already broken.
If the project uses spotless or similar, run it once:
Some projects rely on IntelliJ-imported code style. Import the project's .editorconfig and/or supplied IntelliJ style XML.
Step 6: Make the change¶
Keep it: - Small. 5-line diff > 500-line diff for a first PR. - Focused. One issue per PR. - Tested. Any code change needs a test. Docs-only changes don't.
Run the formatter as you go (or have your IDE do it on save).
Step 7: Run the CI commands locally¶
Whatever your CI workflow does, do it before pushing:
All green? Push.
Red? Fix locally first. Don't push red CI - it makes reviewers babysit you.
If the project's CI runs on multiple Java versions (17 + 21, say), you don't have to test both locally. CI catches version-specific issues.
Step 8: Commit and push¶
Commit message:
- First line ~50 chars, imperative mood ("Add", not "Added").
- Optional blank line + body.
- Reference issue: (#123) auto-links.
If DCO is required:
Push:
GitHub prints a URL - click it to open the PR.
Step 9: Open the PR¶
On the upstream project's GitHub, you'll see a banner: "Compare & pull request." Click.
- Title. Mirror commit message or issue title.
- Description. What changed? Why? What you tested. Reference: "Closes #123" or "Fixes #123" - auto-closes the issue on merge.
- Checklist. Address every item from the PR template.
Submit. CI runs. Wait. Fix anything red by pushing more commits.
If the project requires a CHANGELOG entry, add a line under "Unreleased" describing your change.
What happens next: review¶
A maintainer looks at it. Outcomes:
- "LGTM, merging." Best case.
- "Could you change these?" Most common. Inline comments. Address each - either change code or reply with reason. Push more commits.
- "Thanks, but we don't want this." Rare for
good first issuework. Ask if there's something related you can pick up. - Silence. After a week: "Friendly bump?" After three: ask in any community channel.
Reviews are not personal. Even senior engineers get them. Address efficiently; argue only on substance, not style.
After the merge¶
- Update your fork's
main(step 3 workflow). - Delete the branch locally + on your fork.
- Take a screenshot - you'll be glad later.
- Sit with the experience for a day. Re-read the merged code and review comments. The learning is in the loop.
Worked example template¶
For a docs fix on issue #42 in example-org/example-repo:
# 1-2. Fork on GitHub, then clone:
git clone https://github.com/<you>/example-repo
cd example-repo
# 3. Add upstream:
git remote add upstream https://github.com/example-org/example-repo
git fetch upstream
# 4. Branch:
git checkout -b docs/fix-typo-in-readme
# 5. Set up:
./mvnw verify # baseline green
# 6. Make the change. Edit README.md.
# 7. Run CI locally:
./mvnw verify
./mvnw spotless:check
# 8. Commit and push:
git add README.md
git commit -m "docs: fix typo in installation section (#42)"
git push origin docs/fix-typo-in-readme
# 9. Open the PR. Wait. Respond.
That's the whole thing.
After your first PR: what next¶
- Pick another issue in the same project. Familiarity compounds.
- After 3-5 PRs, become a regular. Watch issues. Answer ones you can. Review other PRs (you don't need to be a maintainer to leave helpful comments).
- Branch out. Try a Tier 2-3 project.
- Build something of your own. Publish it. Iterate.
- Read the "Java Mastery" path when ready to go from "I can contribute" to "I can architect and review."
What you might wonder¶
"PR sits for weeks?" Polite check-in after 1 week. After 3, ask elsewhere.
"Maintainer rude?" Disengage. Thousands of projects.
"Disagree with a review?" Style: do what they say. Correctness: explain with specifics. Either way, stay polite.
"Can't make tests pass?"
Re-read CONTRIBUTING.md. Stuck after an hour: ask in the issue with specifics about what you tried.
"Can I put this on my CV?" Yes. Link to specific merged PRs.
Done with the path¶
You've now: - Installed a JDK and written your first program. - Learned every fundamental: types, control flow, methods, classes, collections, exceptions, records, generics, packages. - Read a real Java OSS project. - Picked a project, prepared a change, submitted a PR.
What you should not do: feel like you "know Java" now. You know what you've been taught. There's much more - concurrency, the JVM internals, Spring, Spring Boot, native images, Kafka/distributed systems. Each is a path of its own.
What you should do: keep contributing. The way you become an engineer is by doing real work on real codebases over time.
Two recommended next paths on this site:
- Java Mastery - 24-week deep dive into the JVM, JIT, GC, Loom, modern idioms. Picks up where this leaves you.
- Container Internals + Kubernetes - most Java services run in containers under Kubernetes. Understanding the substrate makes you a much better Java engineer.
Or just go build something. Programming pays you back when you build.
Congratulations. You are no longer a beginner.