GitHub has the concept of co-authors of a commit. You’ve probably seen it in the web UI, when multiple people are listed to have committed something. I want to be gracious with credit where it’s due and I’ve found ways to make it easier.

The secret to adding co-authors to a commit is adding a trailer to your commit message:

Co-authored-by: Name <email@example.com>

The problem is that neither the name nor the email address are easily accessible in the GitHub web UI. I’ve always scoured the Git history for them to see what data they’re using on GitHub, which is tedious.

Doing it the umpteenth time and getting annoyed, I’ve asked for alternatives and came up with multiple levels of making it easier.

Level 1: View Raw Commits

The first solution I got from Geoff and Matthew is to find any commit by said person on GitHub and append .patch to the URL.

It shows you the commit as if it were a Git patch email with the name and address of the committer in the From header. Here’s a commit of mine:

From c58ffd4e4cba5d5e58356722b985fc362358c48e Mon Sep 17 00:00:00 2001
From: Hynek Schlawack <hs@ox.cx>
Date: Thu, 11 Aug 2022 13:33:34 +0200
Subject: [PATCH] Call abc.update_abstractmethods on 3.10+ (#1001)

---
 changelog.d/1001.change.rst |  3 ++
 src/attr/_make.py           | 34 ++++++++++++++++------
 tests/test_abc.py           | 56 +++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 8 deletions(-)
 create mode 100644 changelog.d/1001.change.rst
 create mode 100644 tests/test_abc.py
 ...

This approach is particularly useful when committing/merging from your phone or tablet, since all it takes is a search and a straight-forward URL manipulation.

Level 2: Use Their GitHub Username

You can have it easier by not bothering with their contact data at all and just use their GitHub username together with an email address scheme:

Co-authored-by: hynek <hynek@users.noreply.github.com>

This has the upside that you’re not exposing the user’s email address at all. They may be using it at the moment, but they can lose access to it in the future (e.g. if it’s a work address), or they may change their stance on using that address in public, because scrapers got annoying.

But what happens if they change their nick? Maybe edgelord69 turns out to be a bad idea after all?

Level 3: Add Their ID

As Sviatoslav pointed out, each user has a permanent ID and new-style anonymous addresses use them together with the username to handle future renames:

Co-authored-by: hynek <41240+hynek@users.noreply.github.com>

One would think 41240@users.noreply.github.com or even Co-authored-by: 41240 should work, but in my experiments it didn’t. It always needs the +username part.


To get that ID you have to query the GitHub API, but the information that you need doesn’t require authorization. You can get it by using cURL to make the HTTP request and jq to extract the JSON field:

$ curl -s https://api.github.com/users/hynek | jq .id
41240

But why stop there? We can make it more personal and also fetch the preferred name from the API!

$ curl -s https://api.github.com/users/hynek | jq --raw-output '.name // .login'

‌--raw-output removes quotes around the name it would otherwise have as a string, and // .login is a fallback to the username for users that haven’t set a name (i.e. the name field is null).

Automation

Since I’m programmer, I didn’t stop there and automated it. Here’s my Fish function:

function ,gcoauthored
    set account $argv[1]

    set data (curl -s https://api.github.com/users/$account)
    set id  (echo $data | jq .id)
    set name (echo $data | jq --raw-output '.name // .login')

    printf "Co-authored-by: %s <%d+%s@users.noreply.github.com>\n" $name $id $account
end

For bash / zsh:

#!/bin/bash

account=$1
data=$(curl -s https://api.github.com/users/$account)
id=$(echo $data | jq .id)
name=$(echo $data | jq --raw-output '.name // .login')

printf "Co-authored-by: %s <%d+%s@users.noreply.github.com>\n" "$name" $id $account

Now, whenever I want to credit someone, all I have to do is call my function with their GitHub username:

$ ,gcoauthored hynek
Co-authored-by: Hynek Schlawack <41240+hynek@users.noreply.github.com>

You can use it inline too:

$ git commit --trailer "$(,gcoauthored hynek)" --trailer "$(,gcoauthored webknjaz)"

Finally, there’s a plugin for GitHub’s gh client: gh-co-author.

Now go forth and give credit – kindness goes a long way!

P.S. Start all of your commands with a comma.