Initial Process

To develop an open-source project, we must first Fork the Repository , as it is not our own project, and we don’t have write access.

Once we fork the repository, an identical copy will appear under our account. We usually refer to the original project as the upstream repo and the forked copy as the downstream repo.

Since we have write access to the forked repository, the first step is to clone it . Note that we should clone our forked repo, not the upstream repo.

For example, if you want to contribute to the kuberay project, and our GitHub username is MortalHappiness, the URL of the upstream repo would be https://github.com/ray-project/kuberay.git, and the URL of our forked repo should be [email protected]:MortalHappiness/kuberay.git (SSH) or https://github.com/MortalHappiness/kuberay.git (HTTPS). Let’s assume we are using SSH.

After cloning, we can run git remote -v, and it should look something like this:

origin  [email protected]:MortalHappiness/kuberay.git (fetch)
origin  [email protected]:MortalHappiness/kuberay.git (push)

Next, we need to add the upstream remote by executing the following commands:

1
2
git remote add upstream https://github.com/ray-project/kuberay.git
git remote set-url --push upstream no_push

In the above commands, replace the URL in the first line with the upstream URL of the project you want to contribute to. The second line is to prevent us from accidentally pushing to the upstream repo. (Although we don’t have write access and can’t push, if one day we become a committer with write access, this line helps avoid accidentally pushing to the upstream.)

Run git remote -v again, and it should look like this:

origin  [email protected]:MortalHappiness/kuberay.git (fetch)
origin  [email protected]:MortalHappiness/kuberay.git (push)
upstream        https://github.com/ray-project/kuberay.git (fetch)
upstream        no_push (push)

The following is my personal habit and is not necessarily required. To avoid accidentally developing features on the master branch (or main branch), I create a local branch to track the upstream/master branch and then delete the local master branch.

1
2
3
git fetch upstream
git checkout -b upstream-master upstream/master
git branch -d master

If you’re using the GitHub CLI , you can also set the default repo to upstream.

1
gh repo set-default https://github.com/ray-project/kuberay.git

Remember to replace the URL in the above command with your upstream URL.

Developing New Features

  1. Ensure that our local upstream-master branch is in sync with the remote:

    1
    2
    
    git checkout upstream-master
    git pull upstream master
    
  2. Check out a new branch, let’s say feature/example:

    1
    
    git checkout -b feature/example upstream-master
    
  3. Proceed with normal development (add, commit, push).

  4. Go to the upstream repo to open a pull request .

Syncing Upstream

If we are in the middle of development and the upstream repo has new commits, we need to sync with the upstream by running git pull upstream master.

Sign-off Commits (DCO)

Some open-source projects require every commit to be signed off. If it’s not done, one of the CI check called DCO (Developer Certificate of Origin), will fail. The sign-off process is straightforward: when you run git commit, you add the -s flag, turning it into git commit -s. This flag automatically appends a Sign-off-by line at the end of your commit message. So, the commit message will look like this:

Some commit message.

Signed-off-by: Chi-Sheng Liu <[email protected]>

Note that this sign-off is different from GPG-signed commits .

If you forget to add the -s flag when committing, you can follow this guide to remedy it.

If you find it cumbersome to add the -s flag every time, you can use a commit-msg hook:

Write the content above into .git/hooks/commit-msg and then execute chmod +x .git/hooks/commit-msg to make it executable.