Intro

This post is about my experience moving from two Github accounts (personal and work) to a single account for all of my contributions. There are some possibly useful scripts that came out of it for others in a similar situation.

To say that Github does not support the merging accounts might be a little unfair (Github docs), but I don’t think that documentation really describes the merging of two accounts. They describe a series of actions that the user (you) must take to achieve (as best you can) the desired goal. Also, there is no Github managed process to trigger these actions.

Why am I talking about merging Github Accounts? Because I wanted to do it and I didn’t know how. I first registered for a Github in 2010 (slcp) but when I started by professional Software Engineering journey in 2019 I created another one for my work (stuartforrest-infinity). After managing both accounts without having a clear definition of which should be used for different things I had repositories and other pieces spread across them both.

I found myself with some downtime and decided to have a look at merging the two, I discovered it is a manual process. To make my life easier I partially scripted the process and in this post will share that with you.

How much can you merge multiple Github accounts?

Merging repositories

The ownership of repositories can be transferred from one account to another (Github docs). This is great news but there are some limitations depending on the kinds of accounts involved so ensure that you have read all the information about this operation. A particularly useful outcome of transferring repositories is that Github will handle redirects from the old repository url to the new one in the new account. This means third parties trying to make use of your repository shouldn’t get lost.

The basic flow for this operation is the account owning the repository initiates the transfer, this can be done from the UI in the settings for the repository, via the API or the Github CLI tool. Once the transfer is the initiated the owner of the account to which it attempting to be transferred to will receive an email asking them to either accept or reject the transfer. This last acceptance/rejection step is not currently possible except via that email, so there is no simple way to programmatically accept the transfers.

To initiate the transfer of all the repositories in the account I no longer wanted to use I put together a bash script that should be general purpose enough for others to use on unix-like systems. The script uses the Github CLI tool and jq to get the job done. The source is here and a simplified version below:

# List the repos in the account
gh repo list --limit 200 --json 'nameWithOwner' > temp-dir/repos.json

# Extract 'owner/repo-name' string for use later
jq -c -r '.[].nameWithOwner' temp-dir/repos.json > temp-dir/repo-urls.txt

# Initiate the transfer for each repo
cat temp-dir/repo-urls.txt | xargs -L1 -I urlpart gh api repos/urlpart/transfer -f new_owner=new-account-name

This is not a destructive operation (the transfer must be accepted first) but testing this on a single test repo would be prudent. Please read the Readme in the repo attached to this post at the end for more detailed information.

Merging gists

Gists cannot be transferred between accounts unfortunately but we can copy Gists between accounts. This was fine for my use case, which was getting everything into one place. If third parties make heavy use of your Gists (e.g. from forum posts) this means that if the original Gists are deleted the links will be broken, and how these Gists get updated needs to be considered. As some third parties may have been linking to my Gists (including this site) I have left my original Gists in the account I am abandoning as well as making copies of them into my active account.

To achieve this I used, again, some bash scripts. The process happens in two parts: export and import

Export

To export the Gists you need to first list them, then parse the list format to extract the Gist id before going back to the Github API to get the full Gist. The full context is in the repository attached to the post but the general idea is as follows:

# List the Gists in the account
gh gist list --limit 200 > $GIST_LIST_FILE

while read -r line
do
    IFS='	'
    # Never figured out why but this helps replace a weird tab character with a normal space
    read -a nicer_formatted_line <<< $line
    IFS=' '
    read -r id rest <<< $nicer_formatted_line[0]

    GIST_DETAIL_FILE="${TEMP_DIR}/${id}"

    # Get the full Gist from Github and write it to file
    gh gist view $id > $GIST_DETAIL_FILE
done < $GIST_LIST_FILE

Import

To import the Gists is relatively simple but can be trickier if you have a mix of Gists with and without descriptions because of how the Gists get formatted when written to file. I only had a small number without descriptions so I chose to add them before importing to make it simple. If that is not an option you would need to first test if they have a description at the head of the file and parse it accordingly.

Importing takes the form of extracting the description and body of the export Gist and creating a new one in the target account using the Github CLI. Again, please see the repository attached to this post for more context.

# List files from the detail dir
for file in "${EXPORTED_DIR}"/*
do
    description=$(head -n 1 $file)
    new_file=$IMPORT_DIR/$(basename -- $file)
    # Remove first two lines because they contain the descripton and a blank line
    sed -e "1,2d" $file > $new_file
    # Using filename (id) create new gist
    gh gist create $new_file -d "${description}" --public
done

Merging commit histories

Depending on how the commits have been authored the commit history/activity in your transferred repositories can also be migrated. If you have chosen to enable the private email address setting in the Github account you are abandoning then a record of that activity cannot be moved to the new account unfortunately. If not, adding the email address to which the commits are attributed to to your new account will allow them show in that account’s activity (it may not be immediate). This does mean the old account (if you are not deleting it, I didn’t) will need to have a different email added as the primary email because you cannot have the same email attached to multiple Github accounts. See the Github docs.

Summary

If your use case is similar to mine I hope this post is helpful in some way in merging multiple Github accounts. In this post we have, ss far as is currently possible, merged two Github accounts to enable sole use of one of them. We have managed to bring all the repositories with us, as well copies of the Gists and in many cases our commit activity from the abandoned account as well. It did the job for me!

There is a repository containing the scripts referred to in this post as well as more context. If they need to be updated that will happen in the repository. It also has more detailed information on how to use them, please read more there before.

Get in contact

If you have comments, questions or better ways to do anything that I have discussed in this post then please get in contact.