How to Submit Code to a GitHub Project
I was setting up a PHP application on a website today, and found some typos and other small bugs that I was able to fix on the code being used in production. Normally, I would have then submitted the changes to the project's bug tracker, but today I decided to go a step further and finally learn how GitHub works. GitHub is a very slick platform, and Git itself is pretty easy to use and has huge popularity, but naturally I ran into a few pitfalls I think I could document better than many of the other tutorials out there which are a bit more general. This is strictly from the perspective of contributing code to an open source project that you do not maintain, but whose development actively occurs on GitHub as a public project. More importantly, since collaborative code is usually something you do after becoming familiar with a version control system, this skips through all of the basics (that aren't as important for this purpose) that can be easily learned by tutorials elsewhere.
Step 1: Create a GitHub account and Install GitHub
This is going to be pretty straightforward. GitHub is a commercial entity, so don't be afraid of the "Signup and Pricing" button on the homepage—it's completely free for open source projects. Create a free account and enter your information. When you're done with that, take advantage of the GitHub Bootcamp guide to setting up Git. This part will vary based on what platform you're on, but you're either going to be installing the command-line tools or one of GitHub's new native clients. I started out only with the Mac mative client, and it was a VERY slick setup process. As long as you don't need to do anything outside of the box, the native client should suit your needs perfectly well for the purposes of this tutorial. (And the Mac app icon is totes adorbz.) There are also now buttons in the GitHub website that tie directly into the app that you can use to clone a repo (but more on that later). One more thing to be aware of here: When creating your account and setting up Git on a client, you will need to enter an email address that will be public to anyone looking at your code submissions. It is possible to have one address that you use to sign up to the GitHub site, and another that will tag all of your code submissions, so just be aware of that.
Step 2: Find the Project and Fork it!
Git is all about forking. If you want to do anything at all to a project's code, you've got to fork it first. This may seem a bit counterintuitive at first, since you probably don't want to create your own unique piece of software based on an existing project, but this is just how Git operates for collaborative coding. If you clone an existing repo and try to make changes to it, you will get nowhere. Chances are you don't have write access to those repos even if they're public. DON'T do it. When you fork a project, GitHub will will essentially create an entirely new repository called UserName/projectname. This means when searching for existing projects, you may run across other users' existing forks. This is entirely normal, and you can easily identify which one is the primary project by the number of Stars and Forks it has.
So step by step, while you're logged into your GitHub account, search for the project you want to submit code to, and click the "Fork" button near the top right of the page. GitHub will create a new repository for you on the GitHub server that contains everything the original project did. NOW you're ready to download some code to your local machine and work on it.
Step 3: Clone the Repository and Branch the Master
If you installed one of the native GitHub clients earlier, at this point you may notice a special looking button on repo pages on the GitHub website. The "Clone in Mac" or "Clone in Windows" buttons can be used to have the native app download and set up your remote repo for you. And once more, you want to clone the repo that you have forked, and thus, have write access to. The one thing about this process that's slightly wonky is that you won't immediately be synced up with any changes that happen to happen to the original project from this point forward. That involves adding the original project as a remote on your local machine, and then fetching updates from it to merge with your own forked repo. I'm not going to go into this because you don't need to configure an upstream remote to submit code to a project you've just forked, and multiple remotes actually aren't supported by the Mac GitHub client at this time, but information on how to do this can be found on Step 3 of the Fork A Repo GitHub Bootcamp page.
Okay, so we've successfully cloned our forked repo to our local machine. Time to change some stuff, right? WRONG. Unless you plan on making a single change and then never touching the project again (and even if you are, it's better to be safe than sorry), you need to create a new branch for each individual change, bugfix, or feature you plan to implement. The reason for this has to do with how changes will later be pulled back into the master project. Features should be given their own branches so that multiple commits can be made on a single feature without commits from other features interfering and getting in the way. When you request to have changes pulled to the original project, it involves the entire branch and all commits on it.
Now then, you've got your forked repo downloaded into your client, or you're working with it using the command line tools. Most large projects will have a master branch (like nightly builds--whatever the bleeding edge is in terms of bug fixes and complete feature implementations), possibly some branches for the last stable release(s), and then a branch for each major feature addition being worked on by the lead developers. If we're just submitting a bugfix or typo, chances are we're going to be working with the master branch on the main project, but that will not be where we implement the fix on our local repo. Branch your local master so you have a copy to work with for your bugfix, name it something appropriate like "bugfix", and then make that your active branch.
Step 4: Make your Change, Commit it, and Push it to your GitHub Repo
Now that we've got a new branch made from the master branch of our fork of the main project, we're ready to change some stuff. Do it, and then commit the change to your active "bugfix" branch, and then feel free to push that branch up to your GitHub repository. This is ridiculously straightforward in the Mac client: you'll see your current branch, the exact files that were changed, and a "Commit & Sync" is all it takes to publish your changes to your GitHub repo.
At this point, if you had other, unrelated bugfixes to make, you would switch to a new copy of the master branch and make your changes in the same way. The result is that every individual feature or bugfix, since they all exist in different branches that were based upon a fork of the current master branch of the main project repository, can be diffed against that main master branch to only show the changes immediately relevant to the feature or bugfix in question.
Step 5: Issue a Pull Request to the Parent Repository
You can read about Pull Requests in-depth here, but basically, you are sending a request to the maintainers of the project to merge one of your branches with theirs. If we want to request that our "bugfix" branch be integrated into the main project, we simply view that branch in our project on the GitHub website, click the "Pull Request" button at the top of the page, write a note to the developers and verify the commit(s) and changed files, and then go for it. It's appropriate to reference IDs of bugs in the bug tracker if you're fixing something that you or someone else has already reported. Again, it is important to note that any commits on the branch you are requesting they merge will be displayed under this pull request. This is why it is so important to create a new branch for each individual feature. If, say, you had another branch where you implemented "feature23" across three different commits, and then issued a pull request for the "feature23" branch, all three commits would be listed. But watch out: if you implement your quick bugfix in one branch and then make your new "feature23" branch from your "bugfix" branch, the bugfix commit will be included when you later try to pull request the "feature23" branch! This is why it is so important to always create your branches from the unchanged master that is in sync with the parent repository.