Contributing to concrete5 on GitHub
Goal: To learn how to properly contribute code changes to concrete5 on github
Prerequisites:
- You must have git scm installed on your machine.
- For this tutorial we will also be using a free GUI (Graphical User Interface) tool for git called Source Tree.
- Create an account on github.com (It's important to note that github is simply a repository storage location for git repositories, git and github are not the same thing. Another very popular git repository is bitbucket, but Concrete5 uses github so we'll stick with that for now).
Introduction
There a numerous open source projects available on the web, but many developers are just learning to develop or have never used any sort of version control system for their source code before. In order for open source projects to work though, I believe that you need a community using the product, reporting issues with it, and improving it. The latter two can both be done very effectively using github, and we're going to focus on how anyone with a little bit of development experience can go about contributing code.
Setting Up GitHub
As mentioned above, GitHub is a website used for storing git repositories and a git repository you can think of as a sort of mini file system tracking software / database, but more on that in a bit. To get started with GitHub you'll simply need to visit their website (https://github.com/) and create an account. Now that you have an account, it's usually preferable to create an SSH key (I find using the git gui client or SourceTree is the easiest way) and adding it to your github account via your account settings. If you choose not to do this that's fine, just know that any time you access github (via push, pull, clone, etc) you will be prompted for your user credentials.
Quick Git Overview
Now that we are ready to start accessing git repositories on github, lets do a quick rundown of what git actually does for us. One might think of git as a file system management / tracking database. I use database pretty loosely since really it is just a bunch of tiny files that exist in the file system wherever your repository sits, but essentially they are there to keep track of file differentials, and it uses git binaries in order to make sense of these files.
Here's some vocabulary that you might find important related to Git/Github:
- Commit - A differential of file changes, this could be file deletes, adds, or changes, and could contain one or many files.
- Branch - Branches are commonly used to create several different workspaces in a single repository. One very common setup is to use a "Master" branch which sort of acts like a trunk that all other branches (usually feature branches) are based off of. So say for instance you wanted to start working on some validation helpers, you could create a "Helpers" branch, and then say part of the way through with that you were told that you needed to go work on the database abstraction layer, you might create another branch based off of "Master" called "dba-fixes". Now you can keep your helpers merges separate from your database merges, which is important to do so that proper vetting of code can happen. After all, you wouldn't want someone reviewing your helper function changes to affect your database changes or vice versa if they weren't dependent on one another.
- Merge - Merging is simply the act of taking 2 branches, and merging the changes together. Keep in mind that this could mean that you are merging your local copy of origin/develop to the github copy of origin/develop, because remember that each of these really is their own repository, even if they are clones of one another. More about merging at git-scm.com.
- Fork - Forking is an important aspect of github rather than git. Forking allows you to create your own copy of a repository on github. This is important because then you are able to create "Pull Requests" from your forked repository.
- Pull Request - The act of asking the forked repository, to merge changes from a forked repository's branch to one of the forked repository's branches. Anyway, most of this will hopefully make more sense after we get through an example, so let's get to it.
Using Github
From here down I'll be giving more specific instructions on how to use Github for the Concrete5.7 repository. The concepts should apply to any git repositories, but specific examples I find are easier to relate to so here goes...
Creating a Fork
- Go to the repository page you wish to Fork. In our case we'll head on over to https://github.com/concrete5/concrete5-5.7.0
-
Click the "Fork" button in the upper right hand corner of the screen, or you can simply add /fork to the end of the url.
-
You will then be redirected to your new forked repository. You can tell that you are on your forked repository by looking in the upper left hand corner of github.
A quick note about forks: Once you have forked the concrete5-5.7.0 repository, you have essentially taken a copy of that git repository at that point in time. Any changes that happen on the concrete5/concrete5-5.7.0 branch will need to be manually merged or rebased into your forked repository in order to receive the latest changes. There is a decent stackoverflow article on how to do this using the git bash tool at http://stackoverflow.com/questions/7244321/how-to-update-github-forked-repository.
Create a Local Clone of the Fork
Now that we've got our very own copy (fork) of the concrete5 repository on github, lets pull that down to our local computer so that we can actually manipulate the code using our favorite IDE or text editor (also worth mentioning, many IDE's have git capabilities built into them that are really kind of nice). To do this we'll fire up Source Tree (link in the pre-requisites at the top of the article).There are those of you who will likely not use Source Tree in favor of the git bash tool, and that's great and you can transfer the concepts here to your own understanding of how that will work. I personally use a mix of the two, because merge conflicts via git bash are simply no fun.
-
Create a local "Clone" of your newly forked repository by clicking the "Clone / New" button in the upper left corner of Source Tree.
-
Next you will need to get the Source Path / URL for your git repository. This can be done by copying the URL fromt he clone URL box on github. Once you have this, copy it into the SourceTree window displayed, and hit the "Clone" button. This will start downloading the forked repository to your computer so it may take a little bit if you are using a slower internet connection (about 100mb as of writing this blog).
Source Tree Window:
-
Once this has completed cloning you should be able to see the repository in the left navigation section of SourceTree. If it is not there however, you can add it by navigating to the cloned repository on your local computer via the File --> Open option inside of SourceTree. Should look something like this:
Creating a Branch
The next step in the process is to create a "Feature Branch". When working with repositories it is always good to separate the different tasks you are working on into their own branches (commonly called feature branches). This way, you can create pull requests for each feature independently of others.
-
To do this in SourceTree, right click on the "Branches" navigation and click "New Branch" (You should ensure that you currently have the "Master" branch set as your current branch before doing this. If it is not, you should "checkout" the master branch.)
-
Next create a meaningful name for your feature branch. Often times if there is a github issue for the feature / fix you are working on using "fixes-####" is a common naming scheme (so if you are working on a fix for issue #123 you would name your branch "fixes-123"). If you're working on something new that doesn't have an issue make it something short and meaningful to you so you don't confuse it with other branches.
-
You should now notice that the new branch has been created and checked out as your current working branch. This means that any commits you make will be applied to this new branch, not to "master" or other branches.
Making Changes to the Repository
At last, we can make our desired changes! You can do this in whatever way you see fit, you can use notepad, vi, sublime, PHPStorm, or any other text editor or IDE you can think of. Modify your files, and watch the changes show up in the "File Status" --> "Working Copy" section in SourceTree.
-
Once you have some changes made, they should start showing up in the "Working Copy Changes" section. There is also a pane on the right that will show you what the change is. If your changes aren't showing up here, it could be because a .gitignore is excluding the file you are changing from the repository. Here's what it looks like when I modify a file to use the full php tag instead of the short tag.
-
The next step towards "saving" these changes would be to "Commit" them. A general rule of thumb, do NOT commit anything that you have not tested yet. If it's not working, it shouldn't be a commit, this helps to prevent breakages in the event a commit rollback needs to take place. Another tip is, the more granular your commits the better. For example, if you wanted to make changes to a file, then format the entire file for psr-2 standards, you should do them as 2 separate commits. This makes it easier when the pull request happens to see what you actually changed, vs what you probably used an auto formatter to do.
Anyway, to commit your changes in SourceTree typically you stage any file you want to commit first, select the files from your "Working Copy Changes" and click the up arrow to "Stage" the changes.
-
Once you have your changes you want to commit in the staging area, simply click the "Commit" button in the upper left corner of SourceTree.
-
And now you get to create a [hopefully] meaningful commit message. This message helps to give a quick overview of what you've changed in this commit and helps others easily decipher what you've done and if it might affect things they are doing, without them having to parse through all the code you just changed. When you commit, you optionally have the ability to "Push" this commit to your forked repository. Assuming that you have tested and will not need to remove this commit, it is safe to check this box that says "Push commits immediately to [origin]".
-
Congratulations, you've now pushed your commit to your forked repository. You can view where each commit is located in SourceTree by clicking back on the "Branches" and selecting the branch you want to look at.
The Pull Request
Back on github, our web interface has been updated to include our new branch. This is where we'll head to give it the once over quick review and submit our pull request back to the motherland (aka Concrete5/Concrete5-5.7.0).
- Head back over to your github.com forked repository (should look something like https://github.com/EC-Joe/concrete5-5.7.0)
-
From there select the "Branches" tab
-
Here you'll find a list of branches that can be found in the fork, as well as those that were brought over from the main repository. What we want to do though, is to create a pull request for our new feature.
-
Finally, we can start the pull request by clicking the nice shiny button. If you're doing this hopefully you feel pretty confident that your code is production worthy and you have tested it yourself. This page also lists a complete overview of all the changes in case you want to give it a second look.
-
Once you have created the pull request, it will generate a pull request / issue number in the Concrete5/Concrete5-5.7.0 repository.
- If you make any changes to the branch you create the pull request on, they will automatically be added to the pull request. This means if you want to work on another issue make a new branch, however if perhaps someone comments on your pull requests, and you realize you need to add something you can certainly do so by.
Removing the Branch
Once your pull request has been merged or close and is no longer needed (it is needed until it gets merged), then you can feel free to delete the branch. This can be done by visiting the pull request and usually at the bottom there is an option to delete the branch. It can also be done from your fork branches page. The final place you will need to remove it from is from your local copy of your fork. This can be done by simply right clicking on the branch in SourceTree and clicking "Delete".
Here's how that looks:
I hope that this will help some more of you get started using git / github and contributing to open source projects. For what it's worth, these are great tools to not only be using for open source, but also in house. There are numerous advantages to using these tools in team environments, but even if you're a one person operation, having the ability to review changes made can often be worth the small extra amount of time it takes to maintain a repository.