Hacker News new | ask | show | jobs
by l72 979 days ago
How do people handle multiple git identities with github+ssh? Since you always log in as the `git` user, you can't reuse keys. I end up with an ~/.ssh/config like:

  Host github-client1
    Hostname github.com
    User git
    IdentityFile ~/.ssh/id_rsa-client1

  Host github-client2
    Hostname github.com
    User git
    IdentityFile ~/.ssh/id_rsa-client2
Then clone using `git clone git@github-client1:username/repo.git` Is there a better way?
19 comments

Different gitconfigs per path on disk, git automatically uses the right identity depending on where you are on disk. Allows you to separate all projects into different users and every repository within those directories will use the specified user.

Main/default config (~/.gitconfig):

  [user]
    email = git@victor.earth
    name = Victor Bjelkholm

  [includeIf "gitdir:/home/user/projects/user-a/"]
    path = /home/user/.gitconfig-user-a

  [includeIf "gitdir:/home/user/projects/user-b/"]
    path = /home/user/.gitconfig-user-b
Then in .gitconfig-user-{a,b}:

  [user]
    name = UserA
    email = UserA@DomainA.local

  [core]
    sshCommand = ssh -i /home/user/.ssh/user_a_id_ed25519
Or, even more separation, create separate users/accounts on the computers you use.
You can also filter based on the remote URL! I find this much more useful than the location of the directory on disk.

  ; include only if a remote with the given URL exists (note
  ; that such a URL may be provided later in a file or in a
  ; file read after this file is read, as seen in this example)
  [includeIf "hasconfig:remote.*.url:https://example.com/\*"]
      path = foo.inc
  [remote "origin"]
      url = https://example.com/git*
Handy, didn't know about that, thanks for sharing!

The reason for doing it by location is probably because my directory structure for projects look something like this:

/home/user/projects/organization/project

so github.com/victorb/neat-project would go into /home/user/projects/victor/neat-project

So my solution is tailored to that structure I suppose :)

Also learning the power of includeIf

At home (I mean a personal box I for personal project and some other public contributions), my directory structure is like:

    ~/sources/forge/organisation/project
where `sources` has the same meaning as your `/home/user/projects` ; and your example will end up here to

    ~/sources/github.com/victorb/neat-project
The structure used has some great influence on solution adopted I think :)
Great tip!

But how could I also select the config for an initial clone of a repo based on the repository address?

Note that this doesn't work if you have a default IdentityKey specified in your ssh config, because `-i` is always unioned with the default IdentityKey in that case (which is a feature, not a bug, of how IdentityKey / `-i` work) and it's possible that that key will be sent to the server before the one you specified in `-i`

Say my IdentityKey that I use for regular ssh is also associated with GH user foo, and then I have the above gitconfig to use a different key associated with GH user bar under certain directories. It's still possible that ssh will try the IdentityKey before the `-i` key when I do git operations under those directories, which means GH will identify me as user foo anyway.

I'm not sure what order ssh uses to sort the union, if any, but at least in my case it seems to always use the IdentityKey before the `-i` key even though it prints them in the opposite order initially (according to `-vvvv`).

And no, `-o IdentitiesOnly=yes` doesn't affect this behavior.

Note that includeIf support can still be spotty in third-party tools/IDEs. Be sure to check that it works everywhere you need it to.
Last I looked, Xcode still doesn't support this. Having it present in the .gitconfig breaks SPM for initial clones and updates.
Does it work with subdirectories?
Yes, anything in /home/user/projects/user-b/ and deeper will use the configured git config for that path.
Awesome, it seems this is the way to go for me then!
I used to do it that way. Recently learned this approach

put this in your ~/.gitconfig-personal

  [core]
   sshCommand = "ssh -i ~/.ssh/github_personal_ed25519"
and this in your ~/.gitconfig-work

  [core]
   sshCommand = "ssh -i ~/.ssh/github_work_ed25519"
This is what I do too, I've written about it in detail at: https://nickjanetakis.com/blog/using-a-custom-ssh-key-to-acc...

You can also set that in your `.git/config` file on a per repo basis. Additionally you can set `GIT_SSH_COMMAND="ssh -i /tmp/custom_key_ed25519 -o IdentitiesOnly=yes" git pull` to override whatever is in your global or repo config for 1 off pulls / clones as a different user.

This is indispensable when you have to clone a repo, so no config settings based on being inside a repo do not apply.
Here's pretty much what I do:

ssh config:

    Host github.com gist.github.com
      Hostname %h
      User git
      RequestTTY no
      RemoteCommand none
      IdentitiesOnly yes
      ControlMaster no

    Match host github.com,gist.github.com exec "~/Developer/C/getargv/bin/getargv -0 -s 1 $PPID | env POSIXLY_CORRECT=1 xargs -0 getopt '46AaCfGgKkMNnqsTtVvXxYyB:b:c:D:E:e:F:I:i:J:L:l:m:O:o:p:Q:R:S:W:w:' | perl -pe 's|.*? -- ||' | fgrep -e username1"
      IdentityFile ~/.ssh/keys/github_rsa

    Match host github.com,gist.github.com exec "~/Developer/C/getargv/bin/getargv -0 -s 1 $PPID | env POSIXLY_CORRECT=1 xargs -0 getopt '46AaCfGgKkMNnqsTtVvXxYyB:b:c:D:E:e:F:I:i:J:L:l:m:O:o:p:Q:R:S:W:w:' | perl -pe 's|.*? -- ||' | fgrep -e company2"
      IdentityFile ~/.ssh/keys/github_rsa2
I set the common github configs in the top Host block, then each Match block looks at the arguments passed to ssh, parses them, and checks for the github username and if it matches, sets the correct key.

The ~/Developer/C/getargv/bin/getargv program is just an implementation of `cat /proc/$PPID/cmdline` for macOS, on linux you don't need a separate tool.

This works for cloning, pushing, pulling, etc.

I have automated that a long time ago with a more reliable/portable solution: https://github.com/dolmen/github-keygen
I was doing this, and sent a question to Github support for a particular thing I was trying to do with my multiple accounts. I got a fairly strong warning about how I was in violation of their service agreement and I could get my subscription terminated if I was found to be using multiple accounts.

It was very odd. Either (a) the person responding to me was uninformed, or (b) that's actually Github's policy and it's not nearly as prominently displayed as it should be.

It's always been very clear in their Terms of Service (which obviously everyone reads carefully...):

The third bullet point at https://docs.github.com/en/site-policy/github-terms/github-t... --

> One person or legal entity may maintain no more than one free Account (if you choose to control a machine account as well, that's fine, but it can only be used for running a machine).

This is the primary reason why I have only ever used my own personal account for work stored at GitHub. If a company is expecting its employees to use a separate work GH account, one assumes that company is planning to pay for all those accounts for its employees.

Having said that, given that many people do use separate GitHub accounts for their separate private and work personas, and many organisations seemingly expect their employees to do so, perhaps GitHub could consider revising this Terms of Service restriction to better reflect reality.

There have also been times when I would like to have access to a second GitHub account for testing purposes. (In particular, for testing GH behaviour when the accounts corresponding to PR commits, PR creator, and PR merger all differ -- see for example <https://github.com/isaacs/github/issues/1368>.)

I maintain two but my personal account is a Pro account.

I imagine some large number of folks that have two accounts are Pro on at at least one of them, if not both.

It's not allowed:

> One person or legal entity may maintain no more than one free Account (if you choose to control a machine account as well, that's fine, but it can only be used for running a machine).

https://docs.github.com/en/site-policy/github-terms/github-t...

I suppose you could pay for additional accounts though.

Anyways, I would use SSH host aliases for this myself as well. Might want to consider `IdentitiesOnly yes` as well.

In context of parent post, I wonder if people realize github is not where git things come from...

"if you choose to control a machine account as well, that's fine, but it can only be used for running a machine"

I'm not aware that "running a machine" has a legal definition. I think it's fine, if you have a corporate account and a private email you are probably fine. I think they mainly have that as some sort of rate limiting legalese, to prevent abuse from "account hopping" i.e. abusing the github api or spamming, etc..

If your work account is a "legal entity", i.e. it is a person under corporate personhood laws, this definition also doesn't really hold water (both you and the corporation account count as legal persons, so this doesn't do much, other than the cost of an incorporation being non-zero). Just don't do weird things with your separate accounts, and actually keep them separate, and you're probably fine.

This is pretty cool.

I'm curious, what are people's opinions about the pro/cons of maintaining multiple GitHub identities like this?

Personally, I have never found it necessary to do this, but about 1/3 to ½ of the people I work with usually have "-companyname" in their usernames, so it appears semi-popular.

What I do is just add my work email as a secondary to my GitHub account and configure the work laptop to use that email, and I generate a new RSA key and add it to my one account. Then I also set up the notifications to use that work email as the notification email for things in that organization

My "Pros" list for doing it this way:

* Simple to configure my git/ssh settings - just add the SSH key on my work laptop to my normal GitHub account

* Easy for someone to identify and even reach me if they were to see a commit in GitHub. For instance, if they know I wrote something they might want to hire me again later to update it.

* I "Sign in with GitHub" to things like developer tools (like Codesandbox, for instance), I get to easily keep control of that account even when I change jobs.

"Cons" I can think of:

* Technically a malicious actor in (or who has compromised) corporate IT could impersonate me by stealing my key from my work-owned computer, cloning my private Github repos, and could introduce changes into other repos I have access to. So I assume if I had high-level access to important OSS projects, this would be a danger for targeted hacking. (Obviously since I can remove the keys at the end of an engagement, I can at least limit my exposure to just current clients/employers.)

Is there anything else that makes you prefer to use a company-specific identity?

Keeping work/private life separate is reason enough to me (also, we don't use Github - we use bitbucket - the decision was made for me!)

Ultimately, I think having work-specific accounts is preferable, and I wouldn't be surprised if a lot of IT departments also prefer this (however, this is also coming from the medical space, where controls are rather tight and security is extremely important and heavily audited)

I've worked for a handful of medical companies, including ones that handle de-anonymized PHI/patient data and/or develop medical devices, both very heavily audited and regulated even in comparison to other medical companies. Using a personal GitHub account attached to an organization on either GitHub proper or GitHub Enterprise was never an issue. Sure we had some folks create a separate account because they wanted to, but there no directive from the IT/security folks even suggesting that, and I'd consider them showing any preference toward not just attaching your personal account a big organization red flag - it means they're just defaulting to "don't do that" rather than actually taking five minutes to understand the constraints and ramifications.
That con was reason enough for me to never do this. Another reason is, when using my personal GitHub account, I'm doing personal things and don't want to see work-related stuff (even if it is just private contributions or the "use SSO to see $employer repositories" message).
The company can mandate SSO, security settings, profile settings like avatar or description, etc that you don't want to apply to your personal account.

Also, once you leave that company, you don't have to worry about unsubscribing from that company's repos, issue threads, etc, or worry about people still @-mentioning you because you participated in those repos before.

about the "cons", another con is that granting access to your unified account from your work or business perspective is "tricky". Github Business accounts can grant specific access only for people identifying with your company's identity provider, like okta or similar. So that can potentially reduce that risk as well, so that your employer can revoke access to okta, and thus revoke access to work repositories, for example. Without that you need to be very strict and do some manual work to grant and revoke accesses.
Curious, why would you need separate ssh keys for the same site? In the above example, you're authenticating the GitHub, not really to client1 or client2.

The only thing that would need to change, AFAIK, is the name and email you use for commits, not necessarily our ssh key.

I do use this:

    [includeIf "gitdir:~/Projects/Client1/"]
       path = ~/Projects/Client1/.gitconfig

    [includeIf "gitdir:~/Projects/Client2/"]
       path = ~/Projects/Client2/.gitconfig
to define the user.name and user.email for different projects
Last I checked, one can't use the same SSH key for multiple github accounts, so if that is part of your workflow then you have to have different keys configured.
True, but I guess I am still wondering why would you need multiple GitHub accounts. I could see 1 for personal and 1 for work but still kind of wonder why. Even in that scenario, you would only need to account for 2 different ssh keys.

Typically, for Client1 and Client2, both clients could invite the same account to the organization.

It depends on the client but several of mine have wanted me to use a separate account with an email for their domain. I suppose this is so they can take over the account rather than just removing my main account.
git config include.path "~/.config/git/id_example"

  ; .config/git/id_example
  [user]
    name = "git"
    email = "git@localhost"
  [core]
    sshCommand = "ssh -i ~/.ssh/id_example"
Configurable per repo with many identities. Add a global alias to engage any identity at any time.

git config --global alias.as-example '!git -c include.path=~/.config/git/id_example'

  git as-example commit -m "my commit message as example"
> How do people handle multiple git identities with github+ssh?

Perhaps not the answer you're expecting (mentioning this anyways, because perhaps it'll be useful/interesting to some folks), but I just ended up paying for GitKraken and suddenly managing multiple accounts (not just GitHub, but also my self-hosted Gitea instance and other servers) became as easy as choosing a different value in a dropdown: https://www.gitkraken.com/blog/managing-mulitple-github-acco...

Paying for something like a Git client felt silly, but at the same time it's good, does what I need and runs on every playform that I use, while also not annoying me too much, same as with JetBrains IDEs and something like MobaXTerm. Before that I used SourceTree and Git Cola because some operations are more convenient with a GUI instead of a CLI, though they didn't have that functionality.

I’ve done exactly this to manage a test user identity separately from my main GitHub identity, for debugging GitHub apps. I didn’t clone separately, though. I added separate remotes to the repo so I could push a branch to either `github` or `github-test`, and those were associated with the separate hosts/identities from my ssh config.
This was a significant problem for me across a few consulting clients. What ended up making things significantly better for me was doing my SSH over GPG: https://opensource.com/article/19/4/gpg-subkeys-ssh This way, I can create and delete GPG subkeys all I want, export the SSH files for upload to a client's system. When it comes time to authenticate, I only ever have to unlock a single secret, which in my case is my GPG keys on my Yubikey devices: https://github.com/drduh/YubiKey-Guide
Why do you need multiple keys for "a few consulting clients" to begin with?

Yubikey's have a limited number of slots for GPG keys by the way... I'm curious to know how you stuffed as many subkeys as you want into the single AUT subkey slot (or even stuffed subkeys usable for authentication into all 4 of the slots it gives you)...

This is what I do.

If you wanted to have it all in your git config, you could set core.sshCommand to "ssh -i ~/.ssh/id_rsa-client", maybe combined with includeIf as in the article (since it's a glob match, you could match on the github org name).

I developed a program to help with this — it's called "gitprof", since it helps with Git profiles. It's not completely flawless but it works fine, and I find it very helpful.

https://github.com/CabbageDevelopment/gitprof

It's what I've been doing up to now, but dealing with git submodules is very painful this way :-( The includeIf approaches on gitdir or remote URL are better in that respect.
Just don't use GitHub and SSH. Git has excellent HTTPS support now, and organising identities around that just plain works better.
It was, but GitHub has basically removed authenticated access via https
I do it this way as well. Works well for me but only because I just have two identities. I think it'd get tedious quickly.
FWIW, note that the `User git` in your config means that you don't need `git@` in the clone command.
Same way