n my last blog post on “Maintaining Code Libraries in PHP,” I talked about the process I went through to update OCLC’s PHP authentication library to use a more modern HTTP client library. At the same time, I was also working on adding new functionality to the library to support a state parameter in requests and directing users to a WAYF (where are you from?) screen for login. Because I was working on these different projects in parallel, I decided to branch the code.
Why branch?
You might be asking yourself why I branched my code if I was working as a solo developer on these changes. Branching is designed to facilitate parallel development, whether that is parallel development by different developers or parallel development of different features. When you are working on different features or functionality, branching keeps you from treading on your own changes.
In my case, adding the WAYF functionality to the library required major restructuring of how particular methods work; I had to make some parameters optional that were required before. My work on the HTTP client upgrade wouldn’t change how the methods were called at all. Co-mingling these changes would increase the complexity of my work and would require me to complete ALL the changes before I could cut a release. Updating the HTTP client was a more pressing development priority, and I didn’t want that slowed down by perfecting the new WAYF functionality, which wouldn’t be deployed until February. So, I cut a branch for the WAYF functionality and worked on that in parallel with my HTTP client changes.
Pulling changes from master into a branch
At this point, you might be asking yourself how I’m going to get my HTTP client changes into my code that has the WAYF functionality. I kind of asked myself this question too. Git offers two ways this can be done: merging and rebasing. If you want an in-depth technical review of each, I suggest you read the Git Tutorial pages on Basic Branching and Merging and Rebasing. I think this line from the Rebasing Tutorial sums it up best: “Rebasing replays changes from one line of work onto another in the order they were introduced, whereas merging takes the endpoints and merges them together.”
I chose to merge my HTTP client changes into my WAYF branch mostly because I’m more comfortable with merging than rebasing, but also because there is a kind of best practice not to rebase commits that exist outside your repository. Rebasing commits that others may have pulled down and used in their own code makes for unhappiness.
Because OCLC uses GitHub for our public code libraries, I used the pull request feature in GitHub to merge the changes. I created a pull request that compared my “wayf” branch with “master,” where I had made the HTTP client updates. GitHub told me there were no conflicts present, so I was then able to merge the pull request automatically. Merging the pull request applied all the changes made in “master” to the “wayf” branch. I ended up doing this a couple times as I found and corrected little bugs in “master.” With these changes applied, I could continue work on my WAYF branch.
In some ways, this made my code history a little messy, but it ensured that I didn’t break anyone who might have been working on my “wayf” branch. I can clean a lot of this up when I merge my WAYF code back into “master.”
Using a specific branch of a code library
For me, a big part of testing the WAYF code was creating a mini PHP application that used it. However, because I wasn’t sure the code was complete and bug free, I didn’t want it in my main code base yet. So, I had to figure out the most effective way to include the branch code in an application. Luckily, Composer is designed to handle this scenario. It is simply a matter of properly configuring your composer.json file in your project. Mine looked like this:
{ "autoload" : { "psr-0" : { "OCLC" : "src" } }, "name" : "OCLC/PlatformTests", "version" : "1.0", "license" : "Apache-2.0", "repositories" : [{ "type" : "git", "url" : "https://github.com/OCLC-Developer-Network/oclc-auth-php.git" } ], "require" : { "php" : ">=5.6", "lib-curl" : "*", "lib-openssl" : "*", "ext-curl" : "*", "ext-json" : "*", "ext-openssl" : "*", "guzzlehttp/guzzle" : ">=6.0", "symfony/yaml" : "~2.3.7", "OCLC/Auth" : "dev-wayf_support", "phpunit/phpunit" : "^5", "behat/behat" : "2.5.0" }, "config" : { "bin-dir" : "vendor/bin" }, "description" : "Tests for OCLC Web Services", "type" : "library", "keywords" : [ "OCLC" ] }
Notice this line:
"OCLC/Auth" : "dev-wayf_support"
This tells Composer that I want to use the “wayf_support” branch of the code. This same syntax can be used if you want to develop against “master” directly, rather than a particular version of the code. I don’t recommend this practice, as it makes your code reliant on something that is unstable. There are a couple potential exceptions to this rule. First, if you need to test a particular version of something, you can develop against “master.” I used this technique to test my WAYF changes. The second exception is if you are working really closely with developers on a project and contributing feedback or even code. I’ve done this when I was writing a code library and had another library as a dependency that I was relying on for changes. However, in this case, I was very much in control and aware of changes being made in my dependencies.
Merging changes from the branch into “master”
Once you're done developing changes in a branch, you can use GitHub to merge the changes back into “master.” This is done by creating a pull request. Creating a pull request will allow you to compare the two different branches to see if there are any conflicts and if the merge can be performed automatically. Once the pull request exists, you can choose to merge it in one of three ways: merge commit, squash and merge, or rebase and merge. I chose to squash and merge in order to make the change history as clean as possible.
Squash and merge is an option that GitHub offers for pull requests, and it allows you to create a more streamlined Git history in your repository. GitHub has a nice post (https://github.com/blog/2141-squash-your-commits) that explains squashing with visuals. The basic idea is that you can take several commits and make them look like a single commit in your version history. In my case, this enables me to take the minutia of the commits I did in the ‘wayf” branch and add that work to “master” as a single commit. If I later need to refer to the details of how the work was done, it is still all broken out in the “wayf” branch.
Community contributed changes to projects
Pull requests can also be used if you are contributing code to a project but don't have committer privileges. In that case, you "fork" the existing project code base into your own repository. What is really happening here is you are using the Git clone command to create a copy of the project in your own GitHub account. This action is similar to branching in the sense that you are making another copy of the code to work from. The difference is that when you "fork" the code in GitHub, you create a copy that exists in a different Git repository from the original project.
Once you have your "fork," you can make changes and then create a pull request based on a comparison across "forks". This process is often how community contributed work is handled within open-source projects managed via GitHub.
For anyone in the community using OCLC's code libraries who wants to fix a bug or make a change, we recommend this method of forking the code base to submit changes and fixes. We welcome pull requests to our libraries from members of the community.
If you're interested in learning more about version control and other best practices for creating applications using APIs, check out our "Five tips for developers creating applications using APIs" workshop at OCLC DEVCONNECT.