Bassam Ismail

Switching Github accounts

17 October, 2023

github

After using my personal account for over a decade, I recently created a new GitHub account for work. This helps me keep the two identities separate and the attribution remains linked to the correct corresponding account.

Transitioning the organizations and repositories was fairly straight-forward. However, I encountered difficulties once I tried to run git pull in one of the work repositories. Later that day, I received a message from my team that one of the GitHub Action was failing. This was because the action was using a token which was generated from my personal account. I generated a new token using the work account and it started working.

The larger issue to address was how to push or pull to repositories linked to two different GitHub accounts. I needed to use two different authentication identity providers. Until now, I was using the GitHub CLI for multiple purposes including authentication, but now it looked like I’d need to switch back to using ssh keys.

I generated two keys for personal and work use:

ssh-keygen -t ed25519 -C "[email protected]" -f $HOME/.ssh/personal -P ""
ssh-keygen -t ed25519 -C "[email protected]" -f $HOME/.ssh/work -P ""

and then configured the $HOME/.ssh/config file to specify the ssh key based on the Host

Host skippednote.github.com
	HostName github.com
	PreferredAuthentications publickey
	IdentityFile ~/.ssh/personal

Host axelerant.github.com
	HostName github.com
	PreferredAuthentications publickey
	IdentityFile ~/.ssh/work

This works great for repositories like github.com/skippednote/dotfiles or github.com/axelerant/create-drupal-theme. Since, GitHub doesn’t have groups, at work we have numerous organizations under our GitHub enterprise like github.com/axelerant-project-dalek or github.com/axelerant-project-kahn. To address this, I’d have to keep updating the config file to add new Host’s. Despite the overhead, this fix works. However, it didn’t seem like a satisfactory solution to me.

All my repositories can be found in the code directory under $HOME. This directory is further divided into two sections: ~/code/personal and ~/code/work. This segregation allows me to execute certain commands based on which directory I’m currently in.

GitHub CLI allows us to authenticate interactively or using a token. The token can be read from a file using:

gh auth login --from-token < FILE_NAME.txt

If a GH_TOKEN environment variable exists, we don’t need have a separate file and this is where direnv would help us.

I generated two different Personal Access Token from my personal and work accounts with repo and read:org scopes assigned.

With two PAT tokens from two different accounts, I created .envrc files under work and personal directories.

touch ~/code/{work,personal}/.envrc

These files were populated with the following content

export GH_TOKEN=[WORK/PERSONAL_GITHUB_TOKEN_VALUE]
export GIT_SSH_COMMAND="ssh -i ~/.ssh/[either `personal` or `work`]"
gh auth login --hostname=github.com

Now every time I cd into a directory under work or personal direnv would use the specified token in the .envrc and log me into the corresponding GitHub account.

Automatically switching GitHub accounts

Using SSH everywhere

The last update to make everything work smoothly is to use ssh instead of https. To make this update globally I updated my global gitconfig file.

git config --global url.ssh://[email protected]/.insteadOf https://github.com/

Switching Email Address

Regardless of which repository I committing to I was seeing my personal email next to my name. A simple work around for this is to override the git author email using direnv. Updating the .envrc to include the work and personal emails resolved this.

export GH_TOKEN=[WORK/PERSONAL_GITHUB_TOKEN_VALUE]
export GIT_AUTHOR_EMAIL=[WORK/PERSONAL_EMAIL_ADDRESS]
export GIT_SSH_COMMAND="ssh -i ~/.ssh/[either `personal` or `work`]"
gh auth login --hostname=github.com

Updates

I noticed that I was seeing both my work and personal accounts showing up on all my commits.

Multiple identities

This happens because your commit has properties for the author and the committer. To override this, I had to set an additional environment variable for the committer: [email protected].