Tips for working with multiple GitHub accounts
I use GitHub for my work and personal projects with different profiles for
each. Because it's a good security/privacy practice, each profile has its
own distinct SSH key. However, this causes problems because the git
CLI
will always try to use the first SSH key that maps to the github.com
domain even if that key has no permissions for the target repository. The
other more straightforward problem with multiple accounts is that the
GitHub.com browser cookie asserts that you are only logged into one account
at a time.
My solutions for these problems are direnv
and Firefox
Containers, respectively. These use cases are straightforward
applications of these technologies, so I'm not claiming any innovation here,
but rather it took me a long time to identify these solutions, and I hope
this saves others some time. If you're not familiar with these tools, read
on for details.
Solution 1: Managing multiple GitHub SSH keys with direnv
The git
CLI respects a GIT_SSH_COMMAND
environment variable, and the ssh
CLI takes a -i
flag to specify an "identity file" or private key. If I run
GIT_SSH_COMMAND=$HOME/.ssh/github-personal git push
, it will try to push the
current repo using my personal github token. However, I don't want to have to
manage setting and unsetting that variable as I switch between work and
personal repositories; I want that setting to "stick" to each repository.
By-and-large, direnv
serves this purpose. It looks for .envrc
files
in the shell's current working directory and its ancestor directories and
sources them automatically as the shell's working directory changes or as the
relevant .envrc
files are changed. It's widely supported and very easy to
install (brew install direnv
) and configure:
# Make sure to add .envrc to your .gitignore!
cd $PERSONAL_REPO && \
echo 'GIT_SSH_COMMAND="ssh -i $HOME/.ssh/github-personal"' >> .envrc && \
direnv allow`
Limitation
This doesn't work if you're using git -C
to run commands on a git repository
outside that is not an ancestor of your current working directory, e.g., if you
are in $HOME
and your personal repo is $HOME/personal
with a direnv envrc
file at $HOME/personal/.envrc
, running git -C $HOME/personal push
will not
trigger direnv
to load your .envrc
file because direnv
hooks into your
shell, not into the git
CLI. To support the git -C
usecase, you'll need to
pass the GIT_SSH_COMMAND
env var to the git
subprocess.
Solution 1 Alternative: the SSH config trick
For a while, I was using the SSH config trick which told ssh
to use my
personal SSH key for requests to the host github-personal
while using my work
key as the default for requests to github.com
. This required me to change my
git config for my private repos to use the github-personal
host. This worked
reasonably well until I wanted to write scripts that worked on my MacBook as
well as in a CI environment--I didn't want to parameterize the host because
that's a weird thing to do--it's always going to GitHub, and any tool that
wants to make authenticated requests to GitHub on my behalf would also have to
support this kind of host parameterization.
Solution 2: Using Firefox Containers for multiple accounts
Firefox has a feature called "Containers" which are basically collections of tabs that share the same cookies, history, etc. Each container is sort of its own browser, in a sense--containers are isolated from each other, as the name implies. So I when I log into GitHub using my personal account in the "Personal" container, I can simultaneously be logged into my work GitHub account on the "Work" container (or rather, the default container, as appropriate) because the two containers don't share cookie jars. When I open a new Personal container tab and navigate to github.com, I'm already signed into my personal GH account, and vice versa for my work account in Work container tabs.
Conclusion
I use these tools for lots of other applications as well, including AWS
(including using direnv
to set AWS_DEFAULT_PROFILE
and
AWS_DEFAULT_REGION
for the aws
CLI) and the Google suite.
If you have other solutions that you've used for similar problems, or feedback or other suggestions, I'd love to hear them. Reach out via Twitter or email (weberc2 / gmail).