You’ve probably watched a video on GitHub explaining how to create a Pull Request.
Fork the repository.
Create a branch.
Make some changes.
Commit.
Push.
Open a PR.
Done, right?
Not quite.
Creating a Pull Request is only one part of contributing to open source. The harder part is understanding what to do before the PR, what maintainers expect inside it, and what happens after you submit it.
Your first contribution isn't simply:
Code → PR → Merge
It's more like:
Find a project → Understand the community → Choose an issue → Fork → Branch → Code → Commit → Push → PR → CI/CD → Review → Changes → Approval → Merge
And every step exists for a reason.
If you're wondering why your perfectly working PR isn't getting merged, you might be missing something that has nothing to do with your code.
This guide will walk through the complete journey of making your first open-source contribution, including forks, commits, branches, PRs, assignees, community guidelines, CI/CD, code reviews, and—most importantly—why each of these things exists.
Before You Write a Single Line of Code
The first mistake many beginners make is opening an issue, choosing a task, and immediately starting to code.
Don't.
First, understand the project.
Look for:
README.mdCONTRIBUTING.mdCODE_OF_CONDUCT.md- Issue templates
- Pull Request templates
- Development/setup instructions
- Existing issues
- Open Pull Requests
Why?
Because every open-source project has its own culture and workflow.
One project might say:
"Comment on the issue before working on it."
Another might require:
"Wait until a maintainer assigns the issue."
Another might welcome direct PRs for small documentation fixes.
If you ignore these instructions, you can end up solving the wrong problem or submitting a PR that doesn't follow the project's process.
The fastest way to contribute isn't always to start coding faster. It's to understand the rules before coding.
Step 1: Find Something to Contribute
Your first contribution doesn't have to be a huge feature.
Look for:
- Bug fixes
- Documentation improvements
- Tests
- Typo fixes
- Small enhancements
- Examples
- Accessibility improvements
- Developer tooling
You may also find labels such as:
good first issue
beginner
help wanted
documentation
bug
enhancement
These labels can help you discover tasks, but don't assume that every good first issue is automatically easy. Read the issue carefully and check its current status.
Why start small?
Your first contribution is also an opportunity to learn the project's workflow.
A small change lets you learn:
Git
+
GitHub
+
Project structure
+
Testing
+
Code review
+
CI/CD
without simultaneously dealing with a massive feature.
Step 2: Understand the Issue and Assignee
Suppose you find:
Issue #123
Fix incorrect validation when username contains spaces.
Before starting, check whether someone is already assigned.
You might see:
Assignees:
@developer123
An assignee generally indicates who is working on the issue.
Why does an assignee matter?
Imagine ten contributors see the same issue and all start implementing it.
You could end up with:
10 contributors
10 implementations
1 issue
That's wasted effort.
An assignment can signal:
"Someone is already working on this."
However, assignment policies differ between projects. Some projects don't use assignees at all.
Always follow the repository's contribution guidelines.
Step 3: Fork the Repository
Suppose the original repository is:
github.com/project-owner/project
If you don't have permission to push directly to it, you can create a fork:
github.com/your-name/project
Think of it as your own remote copy of the project.
Original Repository
│
│ fork
↓
Your Repository
Why?
The original repository belongs to the project maintainers.
Your fork gives you a place where you can safely push your changes without requiring write access to the original repository.
Step 4: Clone Your Fork
A fork exists remotely. Now bring it to your computer:
git clone https://github.com/YOUR_USERNAME/project.git
cd project
You now have:
GitHub
↓
Your fork
↓
Your computer
Why?
Because you need a local environment where you can:
- Edit files
- Run the application
- Run tests
- Run linters
- Debug
- Build the project
Step 5: Create a Branch
Don't immediately start working on main.
Create a branch:
git switch -c fix-username-validation
Now:
main
│
└── fix-username-validation
Your changes go into the new branch.
Why?
Branches keep different pieces of work separate.
Imagine you're working on:
Bug fix
Documentation
New feature
If everything happens directly on main, those changes can become mixed together.
A focused branch makes your contribution easier to understand, test, review, and eventually merge.
Step 6: Make the Change
Now you actually write code.
Suppose the bug is caused by whitespace in usernames.
You modify the appropriate validation logic and add a test.
But here's an important rule:
Don't fix five unrelated things in the same PR.
Avoid turning:
Fix username validation
into:
Fix username validation
+ redesign UI
+ upgrade dependencies
+ rename 40 variables
+ rewrite documentation
Why?
A Pull Request should ideally have a clear purpose.
The easier it is to understand what your PR is trying to accomplish, the easier it is for maintainers to review it.
Step 7: Test Before Creating the PR
This is where many beginners make a mistake.
They think:
"I'll open the PR and let GitHub tell me whether it works."
Don't use CI as your personal debugger.
Run the project's checks locally first.
For example:
pytest
or:
npm test
or whatever the project's CONTRIBUTING.md specifies.
You may also need:
npm run lint
or:
npm run build
Why?
CI consumes project resources and, more importantly, maintainers' attention.
Finding a simple formatting or test failure locally is much easier than discovering it after opening a PR.
Step 8: Commit Your Changes
Once your changes work:
git status
git add .
git commit -m "Fix username validation"
A commit records a snapshot of your work.
Why do commits exist?
Imagine trying to understand a project where the entire history is:
"updated stuff"
"more changes"
"final"
"final 2"
"done"
Not useful.
Good commits provide meaningful history.
For example:
Fix username validation
Add regression test for whitespace
Update validation documentation
The exact commit style depends on the project.
Some projects prefer one clean commit. Others are happy with multiple logical commits.
Check the project's contribution rules instead of assuming there is one universal Git style.
Step 9: Push Your Branch
Your commit currently exists on your computer.
Push it to your fork:
git push origin fix-username-validation
Now GitHub can see your branch.
Your computer
│
│ push
↓
Your fork
│
│ Pull Request
↓
Original repository
Step 10: Create the Pull Request
Now we finally reach the part you've probably seen in those GitHub tutorials.
Open a Pull Request from:
your-name:fix-username-validation
to:
project-owner:main
Your PR should explain:
What changed?
Fixed username validation for leading and trailing whitespace.
Why?
Users entering accidental whitespace were receiving
an invalid validation response.
How was it tested?
Added a regression test and ran the existing test suite.
Step 11: Write a Useful PR Title
Don't write:
Fix
or:
Changes
Instead:
Fix username validation for whitespace
If the project uses Conventional Commits or another naming convention, follow it:
fix(auth): handle whitespace in usernames
Why does the title matter?
Maintainers may have dozens of open PRs.
A useful title immediately tells them what the PR is about.
It also makes the project's history easier to understand later.
Step 12: CI/CD Takes Over
After opening your PR, you might see:
Build ✓
Lint ✓
Unit tests ✓
Integration ✓
Or:
Build ✓
Lint ✗
This is CI — Continuous Integration.
CI automatically runs checks against your changes.
A simplified pipeline looks like:
Push
↓
Build
↓
Lint
↓
Test
↓
Security checks
↓
Report result
Why?
Humans shouldn't have to manually perform the same checks every time someone submits a change.
Automation can catch:
- Broken builds
- Failing tests
- Formatting problems
- Lint errors
- Some security problems
- Compatibility issues
But remember:
Passing CI doesn't automatically mean a PR should be merged.
CI checks what it has been configured to check.
Step 13: Code Review
Now a maintainer reviews your PR.
They might say:
"Can you add a test for this case?"
or:
"This implementation doesn't match the existing pattern. Could you use the helper function instead?"
or:
"Can you update the documentation?"
This is normal.
Why?
Code review isn't just about finding syntax errors.
A maintainer also considers:
- Does the change solve the actual problem?
- Does it fit the project's architecture?
- Is it maintainable?
- Are there enough tests?
- Does it introduce compatibility problems?
- Is the documentation accurate?
Your code can work perfectly and still need changes before it fits the project.
Step 14: Don't Take Review Personally
This is one of the biggest mindset changes when moving from personal projects to open source.
On your personal project:
"It works, ship it."
In an open-source project:
"It works, but does it fit the project?"
A review comment such as:
Please simplify this function.
is about the proposed change.
Treat technical feedback as part of the contribution process.
If you disagree, explain your reasoning with evidence.
For example:
I used this approach because it avoids an additional database
query. I can change it to the existing helper if consistency
is more important here.
That's a productive technical discussion.
Step 15: Make the Requested Changes
Suppose the maintainer asks for a test.
You add it:
git add .
git commit -m "Add validation regression test"
git push
The existing PR automatically receives the new commit.
You usually don't create another PR for every review comment.
The workflow becomes:
PR
↓
Review
↓
Changes requested
↓
Modify code
↓
Commit
↓
Push
↓
CI runs again
↓
Review again
This loop can happen multiple times.
Step 16: Keep an Eye on CI
After pushing changes, CI may run again.
For example:
Tests ✓
Lint ✓
Build ✓
If something fails, read the actual error.
Don't blindly change code until the red check becomes green.
Find out:
What failed?
Why did it fail?
Did my change cause it?
What does the project expect?
Why?
A green CI check is useful only if you understand what it actually verifies.
Step 17: Merge
Once the project requirements are satisfied, the maintainer may merge the PR.
The journey becomes:
Issue
↓
Fork
↓
Branch
↓
Code
↓
Commit
↓
Push
↓
PR
↓
CI
↓
Review
↓
Changes
↓
Approval
↓
Merge
And that's your first contribution.
The Bigger Picture
The Git commands themselves are not the difficult part.
You can memorize:
git clone
git switch
git add
git commit
git push
in a few minutes.
The real skill is understanding the collaboration system around Git.
| Concept | What it does | Why it exists |
|---|---|---|
| Repository | Stores project | Central place for collaboration |
| Fork | Creates your remote copy | Lets you work without direct write access |
| Clone | Downloads repository | Gives you a local workspace |
| Branch | Isolates work | Prevents unrelated changes from mixing |
| Commit | Records changes | Creates useful project history |
| Push | Uploads your branch | Makes your work available remotely |
| Issue | Describes a task/problem | Coordinates work |
| Assignee | Indicates responsibility | Reduces duplicated effort |
| PR | Proposes changes | Enables review before integration |
| CI | Automatically checks changes | Catches repeatable problems |
| Code review | Human evaluation | Checks correctness and project fit |
| Community guidelines | Defines behavior | Keeps collaboration productive |
| Merge | Integrates changes | Adds approved work to the project |
Your First Contribution Checklist
Before opening your first PR:
[ ] Read the README
[ ] Read CONTRIBUTING.md
[ ] Read the Code of Conduct
[ ] Check existing issues
[ ] Check existing PRs
[ ] Confirm the issue isn't already being worked on
[ ] Understand the project's branch conventions
[ ] Fork the repository if required
[ ] Clone your fork
[ ] Create a focused branch
[ ] Make the change
[ ] Add/update tests where appropriate
[ ] Run the project's checks locally
[ ] Create meaningful commit(s)
[ ] Push your branch
[ ] Write a descriptive PR title
[ ] Explain what changed
[ ] Explain why it changed
[ ] Explain how you tested it
[ ] Watch CI
[ ] Respond to review comments
[ ] Fix CI failures
[ ] Wait for approval
[ ] Follow the project's merge process
Final Thought
You probably don't need another tutorial showing you where the "Create Pull Request" button is.
You need to understand what happens before and after that button.
Because creating a PR is easy.
Getting a contribution understood, reviewed, accepted, and merged is the real workflow.
Once you understand the reasoning behind forks, branches, commits, issues, assignees, community guidelines, CI/CD, and code review, open source stops looking like a collection of random GitHub buttons.
It becomes a system:
Understand → Change → Explain → Test → Review → Improve → Merge.
And that's what turns your first Pull Request into your first real open-source contribution.

Top comments (0)