There's an open source project you want to use, but it's missing a feature you need, or has a bug you need fixed. You can implement it yourself, but you want to make sure the patch will be accepted by the project's maintainers. This guide will explain how best to minimize wasted effort and improve the chances of your code being accepted.
I wrote this based on my experience implementing HTML5 media tracks in WebKit and GStreamer. Now that I follow these rules, I generally find it relatively easy to get changes into open source projects.
Note: This guide is not about learning to program. If that's what you're looking for, I recommend this set of projects, which is similar to what a class would give you. Or just take a class.
Before you even talk to the maintainers, start thinking about if your patch can be broken down into multiple atomic patches. The goal of this is to:
- Make your patches easier to review. A patch that can be reviewed in a few minutes will usually be accepted much faster than a patch that takes longer. In some cases, a too-complicated patch will be rejected entirely.
- Reduce your changes vs. upstream. Having more of your code upstream means that merges will be easier (especially important if you plan to be working on this for a long time), and if you're not able to finish your work, some of it will still be useful.
- Allow other people to work in parallel with you. Wouldn't it be nice if you got to the next feature on your list, and someone else had already done it?
Don't take this to mean that you should try to submit incomplete patches — every patch should do something meaningful and work perfectly. What this means is that you should try to make each meaningful, working change into a separate patch.
If you're looking at a project that implements a spec, and you want to implement a newer version of the spec, you should generally try to implement each feature separately. You might even be able to break individual features into multiple patches in some cases.
For example, if you wanted to implement an HTTP/2 feature in a project that currently only supports HTTP 1.1, you could break it down as:
- Implement minimal HTTP/2 feature set
- Implement any features necessary for the one you want (one feature per patch if possible)
- Implement the feature you want
If you're proposing a patch to a "dead" project or a project that isn't the maintainer's primary interest (like someone's website), it can be less work for them if they only have to do one review session. Talk to them to find out if they'd prefer one big patch or multiple small ones (see step 2).
The most important thing you can do when contributing to open source is to communicate with other members of the community. You don't want to write an entire patch and then find out that someone else was already working on it and doesn't need your help, or that your patch implements things in an unacceptable way.
So, figure out how to contact the maintainers and tell them what you plan to do. There are several ways to contact project maintainers, including:
- An issue (or bug) tracker: If a project has one of these, always start by trying to find a match for your bug or feature. You might find that someone is already working on it, or that there is already documentation for how to do it.
- Mailing list: Some projects also have mailing lists or Google groups. These have the disadvantage of being less organized, but are sometimes watched more closely than the bug tracker.
- IRC / Gitter / Slack: Chat rooms can be useful for quick feedback, but not everyone will use the chatroom, and people usually don't monitor chat logs. Once you know who to talk to about a feature, a chat room can be a great way to iterate on ideas quickly.
- Email: If there's no other way to contact the project's maintainer(s), you can try emailing them directly. Don't do this if they have a mailing list or bug tracker. Developers are busy and getting direct emails about bug and feature requests can be overwhelming, and for multi-person teams, the person getting the email may not be the right person to talk to anyway.
If they have an issue tracker and it already has the things you want to implement, just leave a comment on each one saying:
- That you're planning to work on it
- The order you plan to work on issues (if there are multiple)
- That you'd like feedback on your plans
Otherwise, create one or more issues with the same information. Try to match the project's bug-tracking style. Large projects usually want one super-issue for large features ("Implement TLS 1.2") and many sub-issues ("Implement the TLS_RSA_WITH_AES_128_CBC_SHA cipher"). Smaller projects frequently want one issue with multiple pull-requests. Try to guess what they'd prefer and do that. If you think they will want super-issues, start by making that one and ask if you should create sub-issues (unless it's obvious that you should).
Take any feedback they give you into account. This might save you a lot of work.
This part is up to you, but there are a few things you should consider while you do it:
- Try to match the project's style guidelines. This will make maintainers happy, and make your patch easier to review.
- Avoid whitespace changes. This will make your patch harder to review. If whitespace changes are needed, and the maintainers agree, you should make your first patch just fix all of the whitespace issues, since it will be trivial to review that way.
- Some projects have a policy of allowing small whitespace improvements in unrelated patches, to slowly improve the codebase. I don't recommend doing this in your first patch. It's easy to add whitespace changes if the maintainers request it, but it's very difficult to undo them.
- If your patch takes a while to implement (long enough that other patches will come in and get accepted before you submit yours), learn to use
git rebase. Your patch will need to apply to the most up-to-date version of the code when you submit it. Many patches have been lost because they no-longer apply cleanly, and the maintainers don't have time to fix them.
- Make sure any existing tests pass. If the project requires it, write new tests (doing this early will make your code easier to write too!). You might even consider writing tests even if the project doesn't require it. Patches that come with tests tend to be more easily accepted.
Now that you have a nice atomic patch that passes tests, doesn't have superfluous changes, and applies cleanly to upstream:
- Open a pull request or email your patch to the mailing list (whatever people usually do for your chosen project)
- Make any requested changes and resubmit patches until it's accepted
If you've followed the other three steps, this one should go quickly, since the maintainers already know what you're doing and approve of the general approach.
You did it! Your coworkers and/or open-source-using friends will think you're a hero. Hopefully they'll never figure out how easy it is.