I often see people asking how to contribute to an open source project on GitHub. Some are new programmers, some may be new to open source, others aren’t programmers but want to make improvements to documentation or other parts of a project they use everyday.
Using GitHub means you’ll need to use Git, and that means using the
command-line. This post gives a gentle introduction using the git
command-line tool and a companion tool for GitHub called
hub
.
Workflow
The basic workflow for contributing to a project on GitHub is:
- Clone the project you want to work on
- Fork the project you want to work on
- Create a feature branch to do your own work in
- Commit your changes to your feature branch
- Push your feature branch to your fork on GitHub
- Send a pull request for your branch on your fork
Clone the project you want to work on
$ hub clone pydata/pandas
(Equivalent to git clone https://github.com/pydata/pandas.git
)
This clones the project from the server onto your local machine. When
working in git you make changes to your local copy of the repository.
Git has a concept of remotes which are, well, remote copies of the
repository. When you clone a new project, a remote called origin
is
automatically created that points to the repository you provide in the
command line above. In this case, pydata/pandas
on GitHub.
To upload your changes back to the main repository, you push to the remote. Between when you cloned and now changes may have been made to upstream remote repository. To get those changes, you pull from the remote.
At this point you will have a pandas
directory on your machine. All
of the remaining steps take place inside it, so change into it now:
$ cd pandas
Fork the project you want to work on
The easiest way to do this is with hub
.
$ hub fork
This does a couple of things. It creates a fork of pandas in your
GitHub account. It establishes a new remote in your local repository
with the name of your github username. In my case I now have two
remotes: origin
, which points to the main upstream repository; and
joeshaw
, which points to my forked repository. We’ll be pushing to
my fork.
Create a feature branch to do your own work in
This creates a place to do your work in that is separate from the main code.
$ git checkout -b doc-work
doc-work
is what I’m choosing to name this branch. You can name it
whatever you like. Hyphens are idiomatic.
Now make whatever changes you want for this project.
Commit your changes to your feature branch
If you are creating new files, you will need to explicitly add them to the to-be-commited list (also called the index, or staging area):
$ git add file1.md file2.md etc
If you are just editing existing files, you can add them all in one batch:
$ git add -u
Next you need to commit the changes.
$ git commit
This will bring up an editor where you type in your commit message. The convention is usually to type a short summary in the first line (50-60 characters max), then a blank line, then additional details if necessary.
Push your feature branch to your fork in GitHub
Ok, remember that your fork is a remote named after your github
username. In my case, joeshaw
.
$ git push joeshaw doc-work
This pushes to the joeshaw
remote only the doc-work
branch. Now
your work is publicly visible to anyone on your fork.
Send a pull request for your branch on your fork
You can do this either on the web site or using the hub
tool.
$ hub pull-request
This will open your editor again. If you only had one commit on your branch, the message for the pull request will be the same as the commit. This might be good enough, but you might want to elaborate on the purpose of the pull request. Like commits, the first line is a summary of the pull request and the other lines are the body of the PR.
In general you will be requesting a pull from your current branch (in
this case doc-work
) into the master
branch of the origin
remote.
If your pull request is accepted as-is, the maintainer will merge it into the official upstream sources. Congratulations! You’ve just made your first open source contribution on GitHub.
(This was adapted from a post I made to the Central Ohio Python User Group mailing list.)