Skip to content

15 - Your First Contribution

What this session is

The whole thing. We walk through making a real contribution to a real Rust OSS project end to end.

The workflow

  1. Fork on GitHub.
  2. Clone your fork.
  3. Add upstream as remote.
  4. Branch off main.
  5. Set up dev env, including formatters/linters.
  6. Change the code; add a test.
  7. Run formatter + clippy + tests locally.
  8. Push to your fork; open the PR.

Step 1: Fork

GitHub → Fork button (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

Later, to update 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

Follow project's branch-name convention if any.

Step 5: Set up the dev environment

Read CONTRIBUTING.md. Almost always:

cargo test

That installs deps + runs tests. Confirms baseline is green on your machine. If not, stop and figure out why before changing anything.

Also confirm formatter + linter work:

cargo fmt
cargo clippy --all-targets

If the project pins a Rust version via rust-toolchain.toml, rustup will auto-install it on your first cargo command.

Step 6: Make the change

  • Small. 5-line diff > 500-line diff.
  • Focused. One issue per PR.
  • Tested. Any code change needs a test. Docs-only doesn't.

Run cargo fmt after every save (or have rust-analyzer do it).

Step 7: Run CI's commands locally

Whatever the CI workflow runs, run those exact commands:

cargo fmt --all -- --check        # fail if not formatted
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features

All green? Push.

Red? Fix locally. Don't push red CI - it's rude.

For projects with --all-features, run with and without to make sure you didn't break a feature-gated path.

Step 8: Commit and push

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

Commit message: - First line ≤50 chars, imperative. - Optional body. - Reference issue: (#123) auto-links.

If DCO required:

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

Push:

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

GitHub prints a URL to open the PR.

Step 9: Open the PR

On the upstream repo, you'll see "Compare & pull request" - click.

  • Title. Mirror the commit or issue.
  • Description. What changed? Why? What you tested. Closes #123 to auto-close issue on merge.
  • Checklist. Address every item.

Submit. CI runs. Fix anything red by pushing more commits to the same branch.

If a CHANGELOG entry is required, add one.

What happens next: review

Maintainer looks. Outcomes:

  1. "LGTM, merging." Done.
  2. "Could you change these?" Most common. Inline comments. Address each - change code or reply with reason. Push more commits.
  3. "Thanks, but we don't want this." Rare for good first issue. Ask about related.
  4. Silence. After a week: polite check-in. After three: ask elsewhere.

Reviews are not personal. Address efficiently. Argue only on substance.

After the merge

  • Update your fork's main (step 3 workflow).
  • Delete the branch locally + on your fork.
  • Take a screenshot.
  • Sit with it for a day. Re-read merged code and comments. The learning is in the loop.

Worked example

For a small docs fix on example-org/example-repo, issue #42:

git clone https://github.com/<you>/example-repo
cd example-repo

git remote add upstream https://github.com/example-org/example-repo
git fetch upstream

git checkout -b docs/fix-typo-in-readme

cargo test      # baseline green

# Edit README.md

cargo fmt --check
cargo clippy --all-targets
cargo test

git add README.md
git commit -m "docs: fix typo in installation section (#42)"
git push origin docs/fix-typo-in-readme

# Open the PR. Wait. Respond.

After your first PR

  1. Pick another issue in the same project. Familiarity compounds.
  2. After 3-5 PRs, become a regular. Watch issues; help others; review PRs.
  3. Branch out to Tier 2-3 projects.
  4. Build your own crate. Publish to crates.io.
  5. Read the "Rust Mastery" path 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 review?" Style: do what they say. Correctness: explain specifically. Stay polite.

"Can't make tests pass?" Re-read CONTRIBUTING. Stuck after an hour: ask in the issue with specifics.

"PR on CV?" Yes - link to specific merged PRs.

Done with the path

You've: - Installed Rust and Cargo, written first programs. - Learned every fundamental: types, ownership, borrowing, traits, generics, errors, collections, modules, tests. - Read a real Rust OSS project. - Picked, prepared, and submitted a PR.

What you should not do: claim you "know Rust." You know what you've been taught. Much more remains - async, unsafe, lifetimes in depth, FFI, embedded, performance work. Each is a path of its own.

What you should do: keep contributing. Engineering grows by doing real work on real codebases over time.

Recommended next paths on this site:

  • Rust Mastery - 24-week deep dive into ownership, async, unsafe, FFI, traits at depth.
  • Linux Kernel - Rust is now an official kernel language. Understanding the kernel helps any systems programmer.

Or just go build something. Programming pays you back when you build.

Congratulations. You are no longer a beginner.

Comments