A practical guide to the Forking workflow: so easy even a CEO can do it

Updated October 2022 to reflect the fact that Github changed references from master to main.

Here at Sidero Labs, we are an engineering heavy company. Almost every employee is an engineer, and they’re busy doing development to helps make Talos Linux the natural choice for the best Kubernetes operating system, (carrying on the mantle of CoreOS, although not technically spawned from it), among other cool things. Plus, as a worldwide, all remote team, many of our engineers are not native English speakers.

As such, I sometimes note typos, grammatical errors, or general clarification needed on our documentation, and want to be able to fix them without opening issues and requiring the engineers to fix them, which seems overkill for just fixing a typo.

Although I have a programming background, I transitioned to management quite a while ago. Thus, I’d never had the chance to use Github for version control. So I got a crash course in opening pull requests to allow me to improve the documentation of Talos Linux and Sidero Metal. Sidero Labs requires all commits to be signed by our maintainers with Yubikeys for two-factor authentication, as part of our software chain security, which includes code signing, reproducible builds, and so on. As CEO, I am not trusted with this power: I can’t merge changes directly, so a pull request is as far as I can take a change. These are my notes: hopefully they are useful for anyone that isn’t familiar with the forking workflow, and wants to be able to contribute to our projects here at Sidero Labs or to the many other open source projects that use this workflow.

The Forking Workflow is well described in lots of places. This article is more of a concrete, “just-tell-me-what-commands-to-use” thing.

There is a video walkthrough of what this article talks about (indeed, that this article was based on), so you can see it in action if you prefer:

OK! Show me what to do!

Create your own repository

Using GitHub’s web UI, login, then go to the repository you want to contribute to. We are using the Sidero Metal repository as an example. You may as well ‘star’ the repo while you are there.

Use the Fork button in the top right to fork the repository into your own private repo:

You should now be at your own copy of the repository: note the steverfrancis/sidero in the URL instead of siderolabs/sidero.

Use the Code button to copy the clone address:

Now on your workstation, move to the directory you want to use as your workspace, and clone your fork using git clone and the address you just copied:

$ cd ~/workspace
 
$ git clone https://github.com/steverfrancis/sidero.git

Cloning into 'sidero'…
remote: Enumerating objects: 11299, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 11299 (delta 4), reused 11 (delta 4), pack-reused 11288
Receiving objects: 100% (11299/11299), 19.56 MiB | 10.89 MiB/s, done.
Resolving deltas: 100% (5706/5706), done.

$ ls
sidero talos

$ cd sidero

We now have a local copy, but we need to setup more remotes for the Forking workflow. Currently we only have the origin:

$ git remote -v
origin https://github.com/steverfrancis/sidero.git (fetch)
origin https://github.com/steverfrancis/sidero.git (push)

We need to add the main repo (siderolabs/sidero in this case) as a remote. This step only needs to be done once, when you are initially setting up your environment.

Go back to the siderolabs/sidero repo, and again click the Code button and copy the repo URL. We can then add that as an upstream using the git remote add upstream command:

$ git remote add upstream https://github.com/siderolabs/sidero.git

$ git remote -v
origin	https://github.com/steverfrancis/sidero.git (fetch)
origin	https://github.com/steverfrancis/sidero.git (push)
upstream	https://github.com/siderolabs/sidero.git (fetch)
upstream	https://github.com/siderolabs/sidero.git (push)

We can now do git fetch upstream to pull in all the upstream info.

Actually doing edits

This is the part you repeat each time you want to make a new pull request. We will create a new branch for each PR, but you’ll want to be on main branch first before creating a new branch, and ensure it is up to date with the upstream.

git checkout main will switch you to the main branch.

git fetch upstream will pull down updates, and

git reset --hard upstream/main ensures your main branch incorporates the updates.

Now we can make a new branch, via git checkout -b <name of branch>

$ git checkout -b DHCP_Docs_clean
Switched to a new branch 'DHCP_Docs_clean'

This is where you do your edits, using vi or your favorite editor, and then git add the changed files, and commit them locally using git commit -s. Note that in Sidero Labs projects, there should only be one commit per PR, although that commit can cover multiple files.

$ git add .
$ git status
On branch DHCP_Docs_clean
Changes to be committed:
  (use "git restore --staged ..." to unstage)
	modified:   prereq-dhcp.md
$ git commit -s
[DHCP_Docs_clean f44bc4c] docs: edit for clarity and conciseness.
 1 file changed, 8 insertions(+), 21 deletions(-)

Now we just want to ensure that we don’t have any conflicts with the latest code on the upstream, by doing:

git fetch upstream; git pull --rebase upstream main

We can now push the change to our fork (the origin) with git push origin <branch name>. If you’ve forgotten your branch name, git status will tell you. Not that that’s ever happened to me.

$ git push origin DHCP_Docs_clean
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Delta compression using up to 8 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 712 bytes | 712.00 KiB/s, done.
Total 7 (delta 6), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (6/6), completed with 6 local objects.
remote: 
remote: Create a pull request for 'DHCP_Docs_clean' on GitHub by visiting:
remote:      https://github.com/steverfrancis/sidero/pull/new/DHCP_Docs_clean
remote: 
To https://github.com/steverfrancis/sidero.git
 * [new branch]      DHCP_Docs_clean -> DHCP_Docs_clean

Note that in the above output, it told us we can create a pull request simply by visiting: https://github.com/steverfrancis/sidero/pull/new/DHCP_Docs_clean

So we do that, and that’s it! We now have a PR for our change in siderolabs/sidero.

Note

It is not strictly necessary to delete branches after the PR has been merged, although it will not cause any issues to do so.

Subscribe!

Occasional Updates On Sidero Labs, Kubernetes And More!