Hacker News new | past | comments | ask | show | jobs | submit login
Use multiple Git SSH identities on a single computer (github.com/inderdeepbajwa)
99 points by inderdeepbajwa on July 20, 2023 | hide | past | favorite | 59 comments



I manage this with conditional includes in ~/.gitconfig:

  [includeIf "gitdir:~/work/client1/"]
   path = ~/work/client1/.gitconfig
  [includeIf "gitdir:~/work/client2/"]
   path = ~/work/client2/.gitconfig


includeIf directive supports as well conditions based on configured remote URL. [1]

  [includeIf "hasconfig:remote.*.url:https://client1domain.com/**"]
    path = ~/work/client1/.gitconfig
  [includeIf "hasconfig:remote.*.url:https://client2domain.com/**"]
    path = ~/work/client2/.gitconfig
Check comment [2] for a complete example with pinning SSH key and signing key using git-config.

[1] https://git-scm.com/docs/git-config#Documentation/git-config...

[2] https://news.ycombinator.com/item?id=36800853


This is the approach that finally worked for me and have been using this for past 4 years.

I create a top level directory for collection of related repositories. It lets me configure git for different collection of repositories.


In my .ssh/config, I have a section

    Host github_as_pulp
      Hostname github.com
      User git
      IdentityFile ~/.ssh/pulp.../id_rsa
      IdentitiesOnly yes
I just need to replace github.com by github_as_pulp on my clone command to use my second github account. As it remains in .git/config, it matches automatically when I cd between repositories.

In another script, I have GIT_SSH_COMMAND="ssh -i /.../.ssh/id_rsa -F /dev/null" git archive --remote=git@bor...fr:ace/docsite.git master | tar xp docsiteapp

git and ssh are so versatile. I think that a little documentation is better than a new tool.


Same. I skimmed the article, thinking “but that’s already built in?”

I have multiple SSH keys on my computer filling different roles (work, personal, niche hobby stuff). I set them up like you did, and then never think about it again.


> I think that a little documentation is better than a new tool.

Too many people don't enjoy reading the manpages.


I currently use the same thing and the issue is that you can't simply clone repo by copying url, you need to edit it each time. Not sure how does your GIT_SSH_COMMAND achieves in this case?


Came here to make the same comment. I do mostly the same thing (and created an alias to make it less cumbersome to type.)

But... I guess if you didn't want to type this and were okay with an additional dependency, gitid has the advantage that you just have to remember what identity is current.


it'd be nice if the page describes how this tool works and changes it makes.

Since it's unclear i'm not sure how this is useful.

Also you can configure the identity to use in ssh per host using aliases. If you want to switch identities globally, just load the appropriate key in ssh-agent.

here is an ssh config which binds a specific identity to personal.github.com

    Host personal.github.com
       ControlMaster no
       Hostname github.com
       IdentityFile ~/secret/keys/personal/github
       IdentitiesOnly yes
bonus points if you set IdentitiesOnly=yes globally


Been doing exactly this for years. Don't know why I'd need a CLI to switch back and forth. Once cloned using the alias and you never have to worry about it again.


You can do a bit more, even: https://rya.nc/multi-github-accts.html

    Host *.github.com
        IdentityFile ~/.ssh/%h_id_rsa
        IdentitiesOnly yes
        HostKeyAlias github.com
        ProxyCommand nc github.com 22
The `ProxyCommand` hack makes a global `ControlMaster auto` still work with a `%C` based `ControlPath`, but using `Hostname github.com` should work when using something like `%n_%p_%r`.


Why not just use %n in the pattern (hostname as passed on the CLI rather than evaluated in the config) and then `Hostname github.com` inside the `Host` block instead of the latter two commands?


I think you may have replied while I was editing to suggest that.


What's this github subdomain format? Is this a real url you're matching or syntax for something else like your username / org name?


It's a fake subdomain used to select the key.


This doesn't work if you're using an agent like 1Password though and it doesn't handle signing commits with the right key either.


Using git-config it is possible to configure per directory/remote URL different signing keys.

  [includeIf "gitdir:~/work/client1/"]
   path = ~/work/client1/.gitconfig
  [includeIf "gitdir:~/work/client2/"]
   path = ~/work/client2/.gitconfig

 $ cat ~/work/client1/.gitconfig
  [user]
    email = emailforclient1
    name = nameforclient1
    signingKey = 3AA5C34371567BD2
  [core]
    sshCommand = ssh -i ~/.ssh/id_client1


 $ cat ~/work/client2/.gitconfig
  [user]
    email = emailforclient2
    name = nameforclient2
    signingKey = 4BB6D45482678BE3
  [core]
    sshCommand = ssh -i ~/.ssh/id_client2


See:

- https://news.ycombinator.com/item?id=36798978

- https://git-scm.com/docs/git-config#Documentation/git-config...


> npm install -g gitid

Please don’t write command line tools in javascript. I’d never install npm, yarn… on my system just to try a tool out. CLI tools are perfect for compiled languages so you can distribute a binary.


> Please don’t write command line tools in javascript.

This is such a rude thing to say to someone providing free software. If you want to write tools in the language of your choice, then you're free to do so.


How is this rude? Is disagreeing already rude? GP started that sentence with "Please" not with "YOU MUST NOT".


You realize saying "please" doesn't magically make it polite, right?


Please do not sell your products in your own store. I will never shop outside of Walmart just to get your product. Walmart is the perfect distributor of goods so you can get everything you need in one stop.

See how ridiculous it sounds now?


That would mean the original request was unreasonable and not rude.


Luckily, we are talking about an MIT licensed repository of source code that many of us could rewrite as a bash script, and open ourselves to complaints that it doesn't run on windows.

It looks like InderdeepBajwa, specifically, has tried to make a couple of projects in various languages: php, c++, go, python, javascript. So, the refrain 'write what you know' does not quite apply.


Not disagreeing, but isn't npm / yarn being installed basically the same as having make / cmake installed?

This package in question has no dependencies and I can read the source code, can't do that with a binary.

Though I agree, but for other reasons, this tool is a bit silly in JS because you also need node, and it's basically just moving files around.


> isn't npm / yarn being installed basically the same as having make / cmake installed?

Not really as npm and yarn are whole package managers that work in parallel to your distro's standard package manager. They pull various sources (that haven't been vetted by anyone except hopefully by the end programmer who told you to use npm install) from who knows where and install them either in your own home, or system-wide with -g like suggested here.

I would never use npm to install a system tool.


So like anything else that isn't in your package manager... including the latest version.


No. Not everyone lives in Javascript world.


Not everyone lives in C world either


Correct. These are not mutually exclusive positions, and furthermore, this isn't so much to do with languages necessarily, it can be written in brainfuck or use some obscure compiler for all I care.

The issue is fragmenting tools between multiple package managers. That's a pain, and the source of my opposition to this concept here. Doubly so if they're language specific package managers (fine for development/in isolation, not for system wide user facing tools though).


but some OS do by default-ish :D


I dont have (c)make installed


https://www.gnu.org/software/automake/ I will just leave it here.


I’d never download some random person’s binary.


lol I see a lot of tools using npm to distribute binary CLIs written in compiled languages: https://blog.orhun.dev/packaging-rust-for-npm/

people are way more likely to be setup with npm than they are with cargo


cargo? how about winget or choco or any other examples on windows (worst case scenario)


What, no snap?


You don’t need tools for this, run this command once and you’ll never have to worry about using the wrong key for that git repo again:

    cd <git repo>
    git config --local core.sshCommand "ssh -i ~/.ssh/id_<private key to use>"
Job done.


Using `git config` is great. Another option since I don't always remember that command is `export GIT_SSH_COMMAND="ssh -i <private-key>"`

https://git-scm.com/docs/git#Documentation/git.txt-codeGITSS...


Even better, you can set identity as email or commit creator per repo and use private key per machine. Instead of making multiple private keys and god forbid copy these over to other machines.


Saw a few people struggling online when managing multiple git SSH identities on a single user account.

Created a seamless solution for them. It lets you: - create and switch between work and personal SSH accounts in any repository - create new git SSH keys, and switch within existing git repos - upcoming: automatically tie git config user{name, email} to an SSH identity so that your commits follow your identity

Note: It supports Github.com at the moment. Support for any other git provider coming quick!


Can it be used so that different people work on the same repository in the same computer/user account? Like, to easily switch between different identities while committing in one repository.


I tried to figure out how to do this, so that Git Cola would work properly and I could use multiple different GitHub accounts, but couldn't: https://git-cola.readthedocs.io/en/latest/git-cola.html#ssh-... which is a shame because I rather liked that program (staging individual chunks of code and lines within GUI software feels easier than doing the same for entire files with the CLI, in addition to having a visual look at the operations you're about to do)

In the end, I just gave up and forked over some cash for GitKraken, where it's as easy as clicking on a dropdown, in addition to also being cross platform and faster to work with than something like SourceTree. They even have a complete documentation page that describes how to do this exact thing, and it works the same across multiple platforms (Windows and Linux in my case): https://www.gitkraken.com/blog/managing-mulitple-github-acco...

Sometimes paying someone who has solved your exact problem pretty well is the path of least resistance, versus trying to figure out everything yourself. That's more or less why I'm also paying for the JetBrains IDEs, even if most of the software I use is free/open source. Nothing wrong with various scripts and utilities, though!


> Struggling with permission issues when accidentally pushing from a wrong identity file

This is basically only a problem with Azure DevOps, which has a completely broken SSH implementation. It accepts any key, and only later checks permissions. Other source forges do not have this issue, as they only accept keys that have access.

So basically, this might be convenient if you use Azure DevOps, but otherwise there should be no need whatsoever.


Try really hard to fathom why OP would advocate easily breakable NPM/yarn clutter to an otherwise (and admittedly well designed long-standing) solution by ssh `config` and `-i` flag -- if at all not built by other language base e.g C++ Java

If there is a need to use separate identities, without trying to be pedantic, simplest means is via understanding the ssh tooling in POSIX compliant systems. Thinking of solving this everyday operational problem with JS/TS packaging is inventing a new operational problem. NPM might be great for desktop & web application dev, but I wouldn't consider the stability as rock solid - something I will trust my system tasks with.


Fortunately, it's open-source and progressively licensed, so you can rewrite in Zig if you prefer it.


I use the following aliases in my ~/.zshrc file:

  alias workgit="git config user.name 'full name' && git config user.email 'karan@org.tld'"
  alias persgit="git config user.name 'full name' && git config user.email 'karan@my.email'"

I prefer this because there are some overlapping directories in my filesystem and don't want to automatically use another git identity just based on file paths. Works well enough for my usecase.


Just another data point - I use nix + home-manager and have a bunch of servers set up like this;

  programs.ssh = {
    enable = true;
    forwardAgent = true;

    extraConfig = ''
      Host server-one
      HostName 123.0.0.1
      Port 22
      User root
      IdentityFile ~/.ssh/some_rsa

      Host server-two
      HostName 123.0.0.2
      Port 22
      User root
      IdentityFile ~/.ssh/other_rsa
    '';
  };



I'd love for something like this for my workflow, but I don't keep my keys on my disk currently, so I don't think it would work for me.

I currently use KeepassXC to manage my ssh keys, but then get tripped up with the multiple identities sometimes. I have separate keys for personal vs work on github/ gitlab, and when I attempt to perform git push/ pulls, I often have the wrong one in my ssh-agent's keyring.


I've my git config specified like this -> https://github.com/ajayvigneshk/dotfiles/blob/macosx/.config.... This requires the public keys to be available on the `~/.ssh` dir. Works fine with keepassxc's ssh agent for me


In the past I have done this using mulitple .git files. IIRC git searches up through parent directories for this file which can define the user, email and referenced key file (well anything config wise) and you can then split the repositories with different parent directories.

You can also avoid setting the global settings and do it for each repository which depending on how many you have might not be much of an issue.


Am i missing something or is there really a way to do this without doing any other additional steps?


I've liked this one for ages: https://github.com/samrocketman/git-identity-manager

disclaimer: Written by a friend of mine.


This looks better than the one being presented. It says it still has to code the user name and email switching with the SSH key. I.e it doesn't do anything more than the vanilla .gitconfig https://github.com/InderdeepBajwa/gitid#todo

I may try the one you linked....


Does anyone have a link to a simple beginner explainer tutorial to practically setting up keys and SSH (mostly for git and server remote access), but without going too deep or hardcore?


The Pro GIT book has a section to setting up SSH for GIT in section 4.4 [0]. It's comparing various GIT hosting solutions in that chapter so it gets to the point. If you need a refresher, the previous two sections (4.2, 4.3) go over `--bare` git and generating SSH keys, respectively.

[0]: https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-...


What's wrong with ssh-agent?


I just use aliases to git with the ssh.Command directive to switch identities.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: