A maintainer's guide on how to contribute to an open source project on GitHub
This guide is written by the maintainer of the OBS Project, a relatively large open source project which receives about 30-50 pull requests per month. This is meant to be a very concise and to-the-point guide on how to contribute to this (or any) open source project based upon my experience over the years; how to maximize both your contribution efficiency, and how to maximize the efficiency of the maintainers and your fellow contributors.
The Bare Basics
To contribute to a project, you must first have skill using both Git and the programming languages the project uses.
Know how to and how not to use Git
If you are not experienced using Git when you contribute, you will reduce the project's contribution efficiency.
Examples of particularly vital Git skills:
Knowing how to use interactive rebase (
git rebase -i [commit])
Knowing how to squash commits (See: "Knowing how to use interactive rebase" above)
If you plan on making larger or significant changes to the project, knowing how to split commits and use patch mode (
git add -p,
git reset -p,
git checkout -p)
git difffrequently against your changes (especially your unstaged changes before you create a commit)
Knowing how to use GitHub/Bitbucket/etc
If you are just starting out with Git, please see: Git Guides and Other Links
Be able to work with others, and keep your ego in check
Most open source projects are driven by their community; being able to work with others and communication skill are essential requirements. Be willing to listen to others and be patient and do your utmost to prevent discussions from getting needlessly heated. Be willing to make compromises when possible.
How to contribute to open source projects efficiently
Read the project's guidelines
All projects have a specific style of programming that they adhere to. If the project is written in C/C++, their code style may be Allman, K&R/KNF, Google, or GNU. If this is all new to you, it would be wise to learn a little bit about them. There are various styles of code with various indentation styles. If a project comes with a .clang-format file, make sure to utilize that file and run clang-format on your changes before staging. If they use a custom styling and do not use automatic formatting tools, try to look at the project history and emulate that as closely as possible before submission. This project for example uses Linux Kernel style of KNF (Kernel Normal Form).
Every project has their own way of doing things; sometimes they're highly structured, organized, and rigid, and sometimes they're lenient and scrappy. Keep in mind that there are also occasional imperfections, quirks, and inconsistencies in any project as well.
Read the project's git and pull request history
One of the most often overlooked and quickest ways to understand how to make pull requests, changes, commits, or adhere to a project's overall style, is to spend some time going through the project's commit and pull request history. This will allow you to learn how they structure and style their code, their commits, and their commit messages. You can also see what sort of pull requests are typically accepted or rejected and why. Try to understand the project, the way they do things, and try to at least match that or better when contributing.
Making these efforts will save both you and the project a lot of time, and increase the project's efficiency as a whole.
How to make a good commits
When a maintainer reviews your code, they typically don't want to see a jumble of unrelated code in a single commit diff. It's bad for bisecting, makes it hard to review, and more likely to be rejected until corrected. There are a number of good guidelines that typically apply well to almost any open source project:
Do not mix multiple changes in to a single commit: split each unrelated change, however small, in to an individual commit. This makes each specific change easier to review, and makes it so
git bisectcan catch bugs much more efficiently.
Make sure each commit can be fully compiled (and preferably functional) by itself. This ensures the ability to use bisect on that specific change.
Do not include unnecessary changes to existing code, such as code styling changes or whitespace changes.
When submitting a pull request, do not have commits that "fix" a mistake in a prior commit within the pull request unless you are intending to squash it in to that commit later (for example, if the pull request is considered a work in progress). Squash the fix commit in to the commit that it fixes.
git difffrequently on your unstaged changes. Ask yourself if this something that would be easy to read, understand, and review by itself. If not, you may need to split the code in to multiple commits.
Make sure the commit messages are clear and concise: treat the commit message as a brief description and annotation to the code being submitted. The best bet is to follow the 50/72 rule:
First line 50 columns or less (with the exception of the module prefix in our project), present tense, with no ending punctuation.
Second line blank.
Remaining lines are a detailed yet concise description, word-wrapped at 72 columns.
Here is a recent example:
libobs: Add functions to get raw video output Adds obs_add_raw_video_callback() and obs_remove_raw_video_callback() functions which allow the ability to get raw video frames without necessarily needing to create an output.
How to make good pull requests
Similarly, when a maintainer reviews a pull request, they would prefer not to have multiple commits that are unrelated. Ideally, a pull request should be one total overall modification to the project, not multiple.
A pull request should be a set of commits that are all related. If you have multiple changes that are completely unrelated, separate them in to different pull requests. This makes things easier to review, more organized, and more likely to be accepted.
If you want to make a pull request that depends on another pull request, it's recommended (though not necessarily a rule) to hold off on submitting it until the first one has accepted and merged.
Pull request messages should contain a detailed description of what it changes and why it's beneficial to the project.
If your pull request is a work in progress or has an issue, please make sure to note that.
Do not create pull requests from your fork's master branch. Create a new branch to use for the pull request.
On GitHub, a pull request is simply a reference to a branch on your fork. This means you do not have to remake your pull request to update it. Just push to the branch and the pull request will be automatically updated. If you rebased and/or squashed, force push to the branch and the pull request will be automatically updated similarly.
Do not have merge commits within your pull request. See Git Guides and Other Links for more information on how to use Git first.
Get involved with the community
Each project has its own way of managing its community: IRC, mailing lists, forums, Discord, or all of the above. Get involved with the community and get to know the people around it. Contributors should know who the maintainers of the project are. Most projects will have one maintainer, although a few may have more than one, and rarely (such as in the case of the Linux kernel), there will be a hierarchy of maintainers for different subsystems of the project.
Each community is different; some communities are very formal, some are very informal, and then some are somewhere in-between. Some are very friendly, and some are unfortunately not so friendly. Because of this, I highly recommend spending some time getting involved with the community and seeing whether or not you feel comfortable with them.
When not to contribute
Every single new line of code has a maintenance cost.
Due to the fact that open source projects typically have limited resources, the code and features of an open source project usually need to be kept as minimal and focused as possible. Contribute changes that benefit as many people as possible and align with the project's goals.
If you have a feature or change like this that benefits you and people like you specifically, but doesn't necessarily benefit the broader base of users, you should consult the project's maintainers and community on whether or not the change is something they want.
While it's easy to say "my change doesn't hurt anyone", an open source project's maintainers usually want to keep things as slim and focused as possible to minimize maintenance costs and technical debt.
A bunch of small and/or rarely-used features can add up over time; it makes the code progressively more complicated, less readable, makes the project more of a burden to maintain, and reduces the project's overall efficiency little by little.
If your feature does not benefit many users, it may be rejected; however seemingly insignificant of a change. Your needs may simply not match the project's overarching goals and/or the project's focus. The maintainers typically do not mean any offense.
Git Guides and Other Links
- Pro Git (free online book): https://git-scm.com/book/en/v2
- GitHub's Git Handbook: https://guides.github.com/introduction/git-handbook/
- GitHub's Git Cheetsheet: https://services.github.com/on-demand/downloads/github-git-cheat-sheet.pdf