Saltar a contenido

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

  1. Fork on GitHub.
  2. Clone your fork.
  3. Add upstream as a remote.
  4. Branch off main.
  5. Set up dev environment, including any project-specific tools.
  6. Change the code; add a test.
  7. Run tests + checks locally (same commands as CI).
  8. 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

git clone https://github.com/<you>/<project>
cd <project>

Step 3: Add upstream

git remote add upstream https://github.com/<owner>/<project>
git fetch upstream
git remote -v

You should see origin (your fork) and upstream (the real project).

Later, to pull updates from upstream:

git fetch upstream
git checkout main
git merge upstream/main
git push origin main

Step 4: Branch

git checkout -b fix/issue-123-clarify-error-message

Hint at the change. Follow the project's branch-name convention if any.

Step 5: Set up the dev environment

Follow CONTRIBUTING.md. Usually:

./mvnw verify        # or mvn verify, or ./gradlew build

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:

./mvnw spotless:apply

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:

./mvnw verify
./mvnw spotless:check    # if used

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

git add <files>
git commit -m "fix: clarify error message in App.java (#123)"

Commit message: - First line ~50 chars, imperative mood ("Add", not "Added"). - Optional blank line + body. - Reference issue: (#123) auto-links.

If DCO is required:

git commit -s -m "fix: ..."

Push:

git push origin fix/issue-123-clarify-error-message

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:

  1. "LGTM, merging." Best case.
  2. "Could you change these?" Most common. Inline comments. Address each - either change code or reply with reason. Push more commits.
  3. "Thanks, but we don't want this." Rare for good first issue work. Ask if there's something related you can pick up.
  4. 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

  1. Pick another issue in the same project. Familiarity compounds.
  2. 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).
  3. Branch out. Try a Tier 2-3 project.
  4. Build something of your own. Publish it. Iterate.
  5. 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.

Comments