Share
Explore

Working with multiple forks

This is a step-by-step guide to extending an open source project on GitHub and contributing back to the original as well as other forks of the project. You will learn how to build off of older commits as well as how to push changes to other forks that might be out of sync with the original project.
Untitled Diagram.png

Before we get started lets familiarize ourselves with some basic terms

Basic Terms
0
Term
Meaning
1
origin
origin is your fork: your own repository on GitHub, clone of the original repository on GitHub
2
upstream
upstream generally refers to the original repository that you have forked
3
local
a copy of your repository on a local machine like a desktop, laptop or a development server
4
remote
any repository that is hosted on a server i.e. it is not local
There are no rows in this table

Getting started

Start by forking the repository that you want to suggest changes to on Github. This will create a fork of the repository in your account. Typically you will only have read-only access to other repositories. Making a fork of a repository will make a copy of it with write access. You will be using this repository to make changes, test them and creates PRs to the original fork as well as other forks of the repository.
This fork will be your
remote origin

image.png

Making a local copy a.k.a cloning

Next you will make a local copy of your GitHub repository on your computer where you can make changes on it.

Screen Shot 2020-10-17 at 9.40.01 PM.png
git clone <repository url from your fork>


You can clone using SSH or HTTPS URLs. I prefer using SSH over HTTPS as it helps set-up the local repository in fewer steps. In order to use SSH, you will need create SSH keys and update them in GitHub so GitHub can recognize your local computer.

Check your git config

git config -l

...
=<your name>
=<your email>
remote.origin.url=<url of your repository>
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
...

Ensure that you can see these settings. Your name and email will be used to to identify your commits.

Adding remote repositories

It is a good practice to let your local git know of the original repository so it can keep track of other branches as well as allow you to create PRs with other forks. Run these commands from within the root folder of your local repository

git remote add <local name for repository> <remote repository URL>

git remote add lprhodes git://github.com/lprhodes/homebridge-broadlink-rm.git

You can add other forks of the original as remotes as well if you wish to port the changes to those repositories as well.

git remote add ababel git://github.com/AlexanderBabel/homebridge-broadlink-rm.git

You can confirm your settings using either of these commands

git config -l
OR
git remote -v

Your changes

So you can now start making changes that you are interested in. You can make changes on the last commit or you can move back to a previous commit and make changes to that.


If you wish to move back to a previous commit, you can run
git log
to see list of all commits to find the hash id of the commit

If you want to temporarily switch to it, you can then run
git checkout -b <new_branch_name> <commit_id>

If you want to reset the HEAD of your repository back to the old commit and start making changes on that you will first change your local copy to the that commit and then push the changes to your repository. This is useful when your origin has bugs in the latest release and you want to build on top of an older commit rather than a buggy commit.
git reset --hard <commit_id_A>
# Force master branch @origin to update to current local master. This deletes
# all commits newer than commit_id_A from the master branch on origin
git push --force origin master

Next you have two options to create changes

Option 1: Direct commits to master
Open the file in your favorite editor, make changes and save them.

Option 2: Create a new branch and commit to that (preferred)
git branch <new_branch_name>
Open your file in your favorite editor, make changes and save them. This option will allow you to create a pull request (and review) from the new branch into your master branch on origin and review your changes in GitHub before merging them into master.

Commits

You can bundle your changes, “stage” and “commit” them so you can push them to your remote repositories.
Stage:
git add <file names OR .>
Commit:
git commit -m “<commit message”

Finishing changes

Once you have tested your changes and are satisfied with it, you can update your server hosted repository aka origin by running the following command
# Finishing your changes with Option 1 (Direct commit to master)
git push

OR
git push origin master

By default when you push your changes to git they are sent to your remote origin. If you used option 1 above then your changes are directly merged into the master branch.
# Finishing your changes with Option 2 (using a new branch)
git push -u origin <new branch name>

If you used option 2 then the
git push
command will create a new branch at origin and push your commits into that. You can continue with the PR and merge using GitHub Desktop app or

For creating PRs on github.com, go to your repository page on GitHub and then click on branches at the top to view all branches
Screen Shot 2020-11-03 at 12.37.50 AM.png
Click on branches to see all branches including the newly pushed branch

Screen Shot 2020-11-03 at 12.45.11 AM.png

Find your branch and click on new pull request. In the next page, select your master branch of your repository as the head and the new branch on your repository as the base. Review your changes and create a pull request. You can now see a new pull request on your pull requests page

Screen Shot 2020-11-03 at 12.50.06 AM.png
Click on pull requests to see the newly created pull requests

Once you navigate to your newly created PR from the Pull requests page, you can review it and merge it with the master branch.

Porting changes to the forks

Now that you have pushed your changes to your origin, you may want to apply this change to other forks. If you have used Option 2 then you will have your work on a new branch and you can create pull requests by going to the branches page and clicking on the
new pull request
button.

Screen Shot 2020-10-18 at 12.34.01 PM.png

Once there you can select the destination repository that you want to suggest the changes to as shown below.
Screen Shot 2020-10-18 at 12.35.46 PM.png

Here
base
is the repository that you want to suggest changes to and
head
is the repository where you already have changes. In the above example we are comparing and requesting to merge newt10/homebridge-broadlink repository @ branch babel_master_fan_step into lprhodes/homebridge-broadlink @ master

Fork is out of sync with the original repository

In this case the changes that you have made based on the original repository might not be directly compatible or merge well with the other fork “Fork B”. When you try to create a PR you will see multiple commits that are far greater than the changes you made due to this.

In order to limit the changes to your commits only.
git checkout -b <new_branch_name> <remote__other_fork_branch>
OR

git checkout <remote_other_fork_branch>
git branch <new_branch_name> -u <remote_branch_usually_master>

This will create a new local branch called “new_branch_name” and adapt your workspace to the head of “remote_other_fork_branch”

You can now select the commits that you want to apply to this new branch
git cherry-pick <commit_id>

If there are any merge issues fix them using the guidelines
.

Now you can push this new branch to your origin so that you can go to GitHub and create PRs
git push -u origin <new_branch_name>

Once you have the new branch available on GitHub use the steps above to create a PR with the fork that you want to suggest changes to - in this case the other fork “Fork B” that you based your branch on.


References

Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.