This is my work-flow for contributing on Github

Work-flow is very personal, it depends on how we think and what tools we are comfortable with. I strongly believe that reducing cognitive effort is a worthwhile exercise. It leaves more head-space for actual work and return works like compound interest.

Anyways, that’s how I contribute to Github currently. Maybe it will be of interests to others.

It all starts with a project

One hour ago (ok, maybe longer now) I wanted to contribute a package for the Shake Build System to NixOS' nixpkgs repository.

First I need to figure out how it’s structured and how it works.

Github has taken great efforts to make code spelunking more user-friendly but no web solution beats the speed of my own editor. I’m going to take a peek of the project’s but quickly enough I want to have a version of the code sitting on my disk.

For that I have adopted a standardized file-system layout. All projects are living under ~/code/<user>/<project>. Combined with this little shell extension (h) which automatically git clone into the standardized place and cd there I don’t have to think whenever the project has been checked-out or not.

In cases where projects are renamed this system requires some hand-fixing.
$ h nixos/nixpkgs
Cloning into '/Users/zimbatm/code/'...
remote: Counting objects: 14292, done.
remote: Compressing objects: 100% (10096/10096), done.
remote: Total 14292 (delta 467), reused 10580 (delta 349), pack-reused 0
Receiving objects: 100% (14292/14292), 8.74 MiB | 4.27 MiB/s, done.
Resolving deltas: 100% (467/467), done.
Checking connectivity... done.
$ pwd

INFO: When a couple hundred of projects are created in this file structure it can become a bit unwieldy to remember what user was owning which project. h <project> will find the longest match in that structure. autojump is also great for jumping around using fuzzy searches of previously-visited directories.

Coding time

The code is not on some remote server anymore. It makes it easy to start poking around and maybe create a git branch ? Maybe create a commit or two ?

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

One important aspect of contributing is to make sure the code is valid. It must therefore be easy to be able to run the code and hopefully some associated tests. Because I’m living in the shell so much, I want to be able to load different versions of ruby, python, haskell, perl, …​ Each language has their own version-switcher(s). Instead of installing all of them I’ve created a sort of language-agnostic environment loader for the shell called direnv. When moving around with j and h direnv takes care of loading and unloading the appropriate project dependencies.

Here I just want to set the NIX_PATH so that it uses the current project as the source of packages instead of one of the system channels.

$ direnv edit . (1)
export NIX_PATH="nixpkgs=$PWD"
# :wq (2)
direnv: loading ~/.direnvrc
direnv: loading .envrc
direnv: export ~NIX_PATH
  1. opens the ~/.envrc into the $EDITOR

  2. write file and exit the editor

<snip>Actuall coding</snip>


Okay so now there is a branch with some nice code. The fastest way to push that upstream is by using the hub command-line tool.

$ hub fork (1)
Updating zimbatm
remote: Counting objects: 21, done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 21 (delta 4), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (21/21), done.
 * [new branch]      0.5-stable -> zimbatm/0.5-stable
 * [new branch]      xpra14     -> zimbatm/xpra14
new remote: zimbatm
$ git push -u zimbatm shake (2)
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (10/10), 1.18 KiB | 0 bytes/s, done.
Total 10 (delta 7), reused 0 (delta 0)
 * [new branch]      shake -> shake
Branch shake set up to track remote branch shake from zimbatm by rebasing.
$ hub pull-request (3)
shake: new package


shake is a build tool written in Haskell. Since the build tool is not limited
to haskell projects I took the liberty of putting it in the top-level. Is that
alright ?

shake's default.nix is generated with cabal2nix cabal://shake > default.nix
but was missing gcc as a test dependency. Is there a better way to add gcc as a
dependency without having to add it back on the next shake update ?
#:wq (4)
  1. creates a fork to zimbatm/nixpkgs and sets the "zimbatm" remote

  2. push the branch to zimbatm/nixpkgs

  3. opens the editor

  4. write file and exit the editor

Done (waiting on review)


This work-flow is very shell-centric and I love it.