Overview
This article aims to provide a detailed walkthrough of the process for contributing to open source projects on GitHub, with a focus on submitting and managing Pull Requests (PRs). It also addresses common issues that arise during the PR process and how to resolve them effectively.
Why Contribute to Open Source
Contributing to open source is a powerful way to enhance coding skills. Reading and understending the source code of mature open source projects or submitting bug fixes and features demonstrates a deep understanding of programming concepts. For example, studying projects like Kubernetes significantly improved my understanding of Go development and exposed me to best practices used by top developers globally.
Why This Guide
As a maintainer of two open source projects—DevStream (a CNCF project) and Apache DevLake—I frequently encounter issues where contributors submit PRs without following proper procedures. Problems like merge conflicts, disorganized commits, missing commit signatures, and failed CI checks are common. This guide is intended to help newcomers avoid these pitfalls and streamline their contributions.
Getting Started with Open Source Contribution
Choosing the Right Project
- Avoid overly mature projects: Projects like Kubernetes have high competition and may not be welcoming to new contributors.
- Steer clear of very small or early-stage projects: These often lack structure and clear contribution paths.
- Select projects from recognized foundations: CNCF, Apache, and Linux Foundation projects offer a balanced environment for learning and contribution.
Finding Contribution Opportunities
Most open source projects use GitHub Issues to track bugs, feature requests, and documentation improvements. Look for issues labeled "good first issue" or "help wanted." Engage with the community by commenting on an issue to request assignment.
Step-by-Step PR Process
1. Fork the Repository
Use the "Fork" button on GitHub to create your own copy of the project repository. This gives you full write access to experiment and make changes.
2. Clone the Repository Locally
Use Git to clone your forked repository to your local machine. Set up remotes to track the original project:
export WORKING_PATH="~/gocode"
export USER="your-username"
export PROJECT="project-name"
export ORG="original-org"
mkdir -p ${WORKING_PATH}
cd ${WORKING_PATH}
git clone git@github.com:${USER}/${PROJECT}.git
cd ${PROJECT}
git remote add upstream git@github.com:${ORG}/${PROJECT}.git
git remote set-url --push upstream no_push
3. Update Local Branch
Ensure your local branch is up to date with the upstream repository before starting any work:
git fetch upstream
git checkout main
git rebase upstream/main
git checkout -b feat-xxx
4. Make Your Changes
Edit files and implement your contribution. Keep changes focused and well-documented.
5. Commit and Push Changes
Stage your changes and commit them with a signed-off message:
git add .
git commit -s -m "feat: brief description"
git push origin feat-xxx
6. Open a Pull Request
After pushing your branch, GitHub will prompt you to create a PR. Fill out the PR template carefully, including a clear title, description, related issue number, and test results.
7. Merging the PR
If your PR meets all requirements and passes reviews, it will be merged into the main project. If not, you may need to address feedback and update your PR accordingly.
Common Issues and Solutions
Updating a PR After Review
Respond to feedback by making changes locally and pushing them to the same branch. GitHub automatically updates the PR:
git add .
git commit -s -m "fix: address review comments"
git push origin feat-xxx
Combining Commits
Use interactive rebase to squash multiple commits into a single, clean commit:
git rebase -i HEAD~2
In the editer, mark the second commit with "squash" or "fixup" and save. Then force push the updated branch:
git push -f origin feat-xxx
Resolving Merge Conflicts
Online Conflict Resolution
GitHub provides a UI for resolving conflicts directly in the browser. Remove conflict markers and select the desired changes.
Local Conflict Resolution
Update your local main branch and rebase your feature branch:
git checkout main
git fetch upstream
git reset --hard upstream/main
git checkout feat-xxx
git rebase main
Edit conflicting files, stage changes, and continue the rebase:
git add <file>
git rebase --continue
git push -f origin feat-xxx
Fixing Commit Message Issues
Edit the commit message using:
git commit --amend
Force push the updated commit:
git push -f origin feat-xxx
Fixing DCO Sign-Off Issues
Add a sign-off to the latest commit:
git commit --amend -s
Force push the updated commit:
git push -f origin feat-xxx