I’m currently working on a project called Exercism, a programming practice community started by Katrina Owen, an eco-engineer at GitHub, that offers exercises in more than 50 languages. As a user, you can simply download and submit exercises using the command line tool, and once you submit them, you can discuss them with other learners in the community.


Exercism’s community interaction

After playing happily with friends from all over the world for ten days, I felt I could contribute something to the community. Because I’m good at Python, I decided to contribute code for exercism/ Python, the repository. I know many of my friends who use GitHub in “standalone mode” — maintaining their own warehouse without interacting or collaborating with others. Next I’ll share my first experience of using GitHub “online” in the open source world, and show you how to submit a Pull Request (PR) using GitHub Flow.

Before you read this article, you should have:

  1. Git is installed and you can perform basic Git operations from the command line. If you are not familiar with Git, check out Liao Xuefeng’s Git tutorial. If you have confidence in your English, then Learn Git Shoot away interactive tutorial will benefit you even more!

  2. You already have a GitHub account and are familiar with some of GitHub’s basic concepts such as warehouse, Issue, and the core PR we discussed.

  3. Have an ambition to make a difference in the open source community (manual funny).

Look for issues worth addressing

Often, the first step in contributing is to find an Issue worth solving. Choosing the right Issue is not easy. In addition to what you can do, you need to see if anyone has already solved the problem. See if anyone has responded to the Issue, or search the Pull Requests list to see if anyone has already addressed it, or you’re wasting valuable time.


Choose the right Issue

Here we have chosen to address Rational-Numbers: Implement Exercise, and the task is to implement a new exercise called Rational-Numbers. This Issue was chosen because the warehouse maintainer was careful to tell us all the detailed steps to implement the new exercise, and there was no one else to lead the task. Therefore, we reply with “I’ll work on this”, which not only informs the maintainer, but also tells others that we have been responsible for solving the Issue, please do not repeat the effort.

All right, let’s do it!

The preparatory work

Step 1: Fork the original repository

Click the Fork button in the upper right corner of the page and your repository will be generated.


The Fork the original warehouse

The warehouse from Fork

Why Fork someone else’s warehouse first? Can’t I clone exercism/ Python directly to the local computer?

This is fine if you just want to read someone else’s source code, and then you just need git pull every time to get the latest code. But if you’re going to contribute code you can’t just clone it. Because you don’t have write access to exercism/ Python, you can’t use git push to push your changes and you have to Fork them into your own account. GitHub will generate mRcfps/ Python for you (mRcfps is my GitHub username). For this Fork, you have all the permissions (clone, modify, and even delete the repository). At this point, you can make any changes you want.

Step 2: Clone the repository from Fork to local

On the command line, type the following command:

$ git clone https://github.com/mRcfps/python.git
Copy the code

Step 3: Create a new branch


GitHub Flow: New branch creation phase

This step is one of the most overlooked, but it is the first step to start contributing in earnest.

$ git checkout -b impl-rational-numbers
Copy the code

Here I created a new branch, Impl-Rational-numbers, which means Implement (Exercise) Rational numbers. Creating branches that are as easy to remember and recognize as possible has two advantages:

  • It’s much easier to switch jobs across multiple branches
  • Facilitate maintenance by warehouse owners after submitting PR

One question to think about is, why do you need to branch out? Can’t I just change it on the Master branch?

Short answer: Yes, but very, very not recommended.

As defined by GitHub Flow, the Master branch should always be deployable, so development and experimenting on the Master branch is strongly discouraged. GitHub’s PR is branch based, so if you choose the master branch to develop, it will be very difficult to solve another Issue (those familiar with Git might say that you can start a branch by backing back the node, but branch management would be a mess).

Contribute code


GitHub Flow: Contribute code phase

I won’t show you all the work here, but please refer to the code changes here.

$ git status On branch impl-rational-numbers Changes not staged for commit: (use"git add <file>..." to update what will be committed) (use"git checkout -- <file>..." to discard changes in working directory) modified: config.json modified: exercises/rational-numbers/example.py modified: exercises/rational-numbers/rational_numbers.py modified: exercises/rational-numbers/rational_numbers_test.py modified: exercises/rational-numbers/README.md no changes added to commit (use "git add" and/or "git commit -a")Copy the code

Ok, then we commit:

$ git commit -am "rational-numbers: implement exercise"
Copy the code

Submit work


GitHub Flow: Commit PR phase

Now comes the exciting moment: submit our contributed code!

First, we need to commit the changes to mRcfps/ Python, which is our own remote repository.

$ git push -u origin impl-rational-numbers
Copy the code

The -u option is equivalent to — set-upstream. Imp-rational-numbers is the branch we just modified. Then, we open mRcfps/ Python, which we Fork into the repository, and see a slight change:


The repository from Fork automatically detects the newly committed branch

In fact, if you open exercism/ Python, that’s what you’ll see. Then click on the Compare & Pull Request button to start editing our PR:


Edit PR information

When using fix(es), close(s), or resolve(s), if the Pull Request is merged, the corresponding Issue is automatically closed. Do-numbers: Implement I’ve tagged go-1300 here so that the rational-numbers: Implement exercise Issue goes off as our contributed code is accepted Using the GitHub keyword correctly can greatly facilitate the repository maintainer so that they don’t have to find the corresponding Issue and manually close it.

Click Create Pull Request to submit!

Discussion and review


GitHub Flow: Review discussion phase

Then came the waiting. The next day we woke up to find that the warehouse maintainer had replied to us.


The maintainer conducts code reviews

He pointed out that there was a problem with our modified config.json and suggested changes. As for his hand shaking accidentally approve our modification don’t care (again manual funny).

After finishing the modification according to his suggestion, we submitted the new modification.

$ git commit -am "rational-numbers: fix topics in config.json"
$ git push
Copy the code

You can open the PR page to check our new modifications.


The new changes appear on the Pull Request page

Deployment phase


GitHub Flow: Deployment phase

The warehouse maintainer approved our changes!


The maintainer deployed our changes

Then he incorporated exercism/ Python’s master branch into our Imp-Rational-numbers branch. Why would he do that? Because while we’re working on that branch, exercism/ Python’s master branch might commit some new changes and our branch might not be up to date.


New changes on master make our branch obsolete

By incorporating the Master branch into our branch, our branch is Ready to Deploy. If CI (continuous integration, covered later) fails at this point, it means that our branch is not ready to deploy and needs to be modified or even rolled back. But here, our merged branch passes the CI test.

Consolidation phase


GitHub Flow: Merge phase

The maintainers then formally incorporated our branch into the master branch of exercism/ Python, and that was the culmination of our PR and our contribution to the original repository!


The maintainer merged our branches

Since imp-Rational-numbers have been merged and can be safely removed, we click the Delete Branch button to remove the branch in our remote repository mRcfps/ Python. Then enter the following command locally to delete the local branch:

$ git branch -D impl-rational-numbers
Copy the code

Why use -d for forcible deletion? Because imp-Rational-numbers is not locally merged with the MASTER branch of mRcfps/ Python (don’t get confused, we just merged with exercism/ Python’s master). Our own master branch recommends synchronization using the methods described below.

Some supplement

That concludes my introduction to the PR life cycle. I’m going to talk about some of the more important aspects of this.

Keep the repository from Fork in sync

If other contributors submit code to exercism/ Python, or if we submit our own code, our mRcfps/ Python will become obsolete. Always keep our forked warehouses in sync with the original ones to minimize the chance of collisions. Let’s use the mRcfps/python repository we Fork to keep exercism/python in sync.

First, look at what remote repositories mRcfps/ Python has. There should only be Origin.

$ git remote -v
origin  https://github.com/mRcfps/python.git (fetch)
origin  https://github.com/mRcfps/python.git (push)
Copy the code

Then, add exercism/python to our remote repository and name it upstream (or you could call it something else, but it’s more convenient by convention).

$ git remote add upstream https://github.com/exercism/python.git
Copy the code

Let’s see if remote has something added to the list…

$ git remote -v
origin  https://github.com/mRcfps/python.git (fetch)
origin  https://github.com/mRcfps/python.git (push)
upstream        https://github.com/exercism/python.git (fetch)
upstream        https://github.com/exercism/python.git (push)
Copy the code

Upstream is already in remote list! Then we can sync easily. Make sure you’re on the master branch, then grab upstream’s changes and merge with our local Master branch.

$ git checkout master
$ git fetch upstream
$ git merge upstream/master
Copy the code

Push local updates to Origin, our GitHub repository:

$ git push
Copy the code

Sync job done!

Continuous integration

Many open source projects use Continuous Integration (CI) to ensure code quality. For us contributors, this means that every time we submit PR and continue pushing code, THE CI builds on our submission and performs the checks specified by the repository maintainer, such as code style checks, unit tests, and so on.

If you look at your newly submitted PR, you’ll see a yellow circle in the upper right corner, which means CI is checking your submission.


CI is checking our PR

When the yellow circle in the upper right turns into a green tick, your code passes CI!


This PR passed the CI

Sometimes a Red Cross appears, indicating that a CI test has not been passed.


This PR failed to pass CI

At this point we need to go to the PR page, scroll to the bottom, see the details of the Travis-CI check (the repository uses the popular Travis CI), find out the cause of the error, make changes, and git push to commit our changes until they pass the CI.

conclusion

Maybe the steps are a little complicated, so here’s a summary of the Pull Request lifecycle:

  1. Identify projects to contribute to and look for issues worth addressing.

  2. Fork the original repository into your own account and clone it locally.

$ git clone https://github.com/<YOUR_USERNAME>/<FORKED_REPO>.git
Copy the code
  1. Open a new branch, modify the code, and commit.
$ git checkout -b <NEW_BRANCH_NAME>
$ git commit -am "<COMMIT_MESSAGE>"
$ git push -u origin <NEW_BRANCH_NAME>
Copy the code
  1. Open the GitHub page of the repository, click the Compare & Pull Request button as prompted, fill in the PR information (remember to close the corresponding Issue using GitHub keywords) and submit.

  2. If the CI test fails, or the repository maintainer requests changes, the code continues to be modified locally, and Git pushes commit again until it is reviewed by both the CI and repository maintainer.

  3. The repository maintainer deploys and merges into your branch, contributing to completion.

Practice personally

The GitHub repository for this article is here, so feel free to make an Issue or Pull Request. If you just want to try out the above for yourself, feel free to post your THOUGHTS to me in thoughts.md and I’ll merge your branches as soon as possible. Of course, if you have any suggestions to improve this article, you are more welcome to Pull Request and make this article better!