How to tell git which private key to use?
Solution 1
In ~/.ssh/config
, add:
Host github.com
HostName github.com
IdentityFile ~/.ssh/id_rsa_github
If the config file is new, you might need to do chmod 600 ~/.ssh/config
Now you can do git clone [email protected]:{ORG_NAME}/{REPO_NAME}.git
- Where
{ORG_NAME}
is your GitHub user account (or organization account)'s GitHub URI name.- Note that there is a colon
:
aftergithub.com
instead of the slash/
- as this is not a URI.
- Note that there is a colon
- And
{REPO_NAME}
is your GitHub repo's URI name - For example, for the Linux kernel this would be
git clone [email protected]:torvalds/linux.git
).
NOTE: On Linux and macOS, verify that the permissions on your IdentityFile
are 400. SSH will reject, in a not clearly explicit manner, SSH keys that are too readable. It will just look like a credential rejection. The solution, in this case, is:
chmod 400 ~/.ssh/id_rsa_github
Solution 2
Environment variable GIT_SSH_COMMAND
From Git version 2.3.0, you can use the environment variable GIT_SSH_COMMAND
like this:
GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example" git clone example
Note that -i
can sometimes be overridden by your config file, in which case, you should give SSH an empty config file, like this:
GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example -F /dev/null" git clone [email protected]:example/example.git
Configuration core.sshCommand
Since Git version 2.10.0, you can configure this per repo or globally, using the core.sshCommand
setting. There's no more need to use the environment variable. Here's how you clone a repo and set this configuration at the same time:
git clone -c "core.sshCommand=ssh -i ~/.ssh/id_rsa_example -F /dev/null" [email protected]:example/example.git
cd example/
git pull
git push
If the repo already exists, run:
git config core.sshCommand "ssh -i ~/.ssh/id_rsa_example -F /dev/null"
The configuration is saved in .git/config
Solution 3
There is no direct way to tell git
which private key to use, because it relies on ssh
for repository authentication. However, there are still a few ways to achieve your goal:
Option 1: ssh-agent
You can use ssh-agent
to temporarily authorize your private key.
For example:
$ ssh-agent sh -c 'ssh-add ~/.ssh/id_rsa; git fetch user@host'
Option 2: GIT_SSH_COMMAND
Pass the ssh arguments by using the GIT_SSH_COMMAND
environment variable
(Git 2.3.0+).
For example:
$ GIT_SSH_COMMAND='ssh -i ~/.ssh/id_rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' \
git clone user@host
You can type this all on one line — ignore $
and leave out the \
.
Option 3: GIT_SSH
Pass the ssh arguments by using the GIT_SSH
environment variable to specify alternate ssh
binary.
For example:
$ echo 'ssh -i ~/.ssh/id_rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $*' > ssh
$ chmod +x ssh
$ GIT_TRACE=1 GIT_SSH='./ssh' git clone user@host
Note: The above lines are shell (terminal) command lines which you should paste into your terminal. They will create a file named ssh
, make it executable, and (indirectly) execute it.
Note: GIT_SSH
is available since v0.99.4 (2005).
Option 4: ~/.ssh/config
Use the ~/.ssh/config
file as suggested in other answers in order to specify the location of your private key, e.g.
Host github.com
User git
Hostname github.com
IdentityFile ~/.ssh/id_rsa
Solution 4
Use custom host config in ~/.ssh/config
, like this:
Host gitlab-as-thuc
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa.thuc
IdentitiesOnly yes
then use your custom hostname like this:
git remote add thuc git@gitlab-as-thuc:your-repo.git
Solution 5
If you need to connect to the same host with different keys then you can achieve it by:
- Configure the
~/.ssh/config
with different Hosts but same HostNames. - Clone your repo using the appropriate host.
Example:
~/.ssh/config
Host work HostName bitbucket.org IdentityFile ~/.ssh/id_rsa_work User git Host personal HostName bitbucket.org IdentityFile ~/.ssh/id_rsa_personal User git
Then instead cloning your repos like:
git clone git@bitbucket.org:username/my-work-project.git git clone git@bitbucket.org:username/my-personal-project.git
you must do
git clone git@work:username/my-work-project.git git clone git@personal:username/my-personal-project.git
Related videos on Youtube
jrdioko
Updated on September 17, 2022Comments
-
jrdioko over 1 year
ssh
has the-i
option to tell which private key file to use when authenticating:-i identity_file
- Selects a file from which
the identity (private key) for RSA or DSA authentication is read.
The default is
~/.ssh/identity
for protocol version 1, and~/.ssh/id_rsa
and~/.ssh/id_dsa
for protocol version 2. Identity files may also be specified on a per-host basis in the configuration file. It is possible to have multiple-i
options (and multiple identities specified in configuration files).Is there a similar way to tell
git
which private key file to use on a system with multiple private keys in the~/.ssh
directory?-
Flimm about 9 yearsSee this question in StackOverflow as well.
-
Machavity almost 8 yearsAlso related serverfault.com/questions/194567/…
-
Admin almost 2 yearsDon't mess around with all the host-based top-rated answers. See Dmytro Buryak's path-based answer instead.
-
-
Valentin Klinghammer over 11 yearsWhat if you need to connect to the same host with different keys?
-
dolmen over 10 yearsI'm using this trick in my
github-keygen
tool that I built to manage SSH keys and settings for Github. -
Sithsu about 10 yearsAnother explanation of how to do this.
-
Grissiom over 9 years@Cliff Nop, in my manpage: "
HostName
: Specifies the real host name to log into. This can be used to specify nicknames or abbreviations for hosts." My ssh version is openssh-6.7p1. -
Cliff over 9 years@Grissiom That's exactly what it says. But you seem to understand the meaning backwards. Host (or Match) is required. To create a host nickname you place the nickname in the Host line and the real hostname in the HostName line. Examples: saltycrane.com/blog/2008/11/…
-
hek2mgl about 9 years
~/.ssh/config
Is the way to go. -
Nathan Basanese over 8 years// , What if your identity in ssh-agent is forwarded, though, as in this question? superuser.com/questions/971732/…
-
Nathan Basanese over 8 years// , Excellent solution. I wonder, though, if this would allow one to specify an identity passed through using agent forwarding. Most of my keys are not local to the servers I am using them on. I asked about this here: superuser.com/questions/971732/…
-
flaviovs over 8 yearsThe answer deals only with a way of specifying arbitrary command lines to be used as git repositories. IMHO, you should try to sort out your issue using ssh alone first (e.g. "ssh host" should connect using the right key). I will try to provide more info on your other question, though.
-
flaviovs over 8 yearsRe my last comment, for some reason I cannot comment in your other question -- and do not have a concrete answer. Well, you might want to checkout serverfault.com/questions/599560/… and the answer from user kasperd.
-
Adam Franco over 8 yearsThis answer was exactly what I needed to force Chef's
git
resource to use repository-specific deployment keys to clone/fetch from private Github repositories. The additional advantage of this method over the environment/script based ones is that since the key-path is encoded in the working-repo's config, it will use the same key on both initial clone and subsequent fetches/pushes. -
Abdull over 8 yearsI had to export the shell variable to an environment variable to make this work, i.e.
export GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example"
, thengit clone example
-
bsumirak over 8 yearsI work on a machine (A) from which I git push to a server (B) that only accepts ssh key authentication. While my ~/.ssh/config setup on (A) works perfectly fine when I work directly on that machine, it does not when I login from some other location (C). Using
$GIT_SSH
and a script solved this problem. Thanks! -
Flimm over 8 years@Abdull In Bash, doing the assignment on the same line as the command exports the environment variable for just that command. Try it:
example=hello /usr/bin/env | grep example
. -
Alexis Winters over 8 yearsI've allowed me to reformat this post: IMO this is by far the most comprehensive answer. In its original design, a quick scan suggested the post where describing a single complicated solution to the problem, so I missed it.
-
elysch about 8 yearsIf the config file is new, don't forget to do
chmod 600 ~/.ssh/config
-
Piotr Findeisen about 8 yearsThanks. Just note: use "$@" instead of $* for pass-thru arguments, as the former behaves correctly when arguments contain whitespace.
-
Jan Vlcinsky about 8 years@PiotrFindeisen Thanks for your note. However, I do not understand it completely - in zsh it helps me to keep strings with space in one piece, but in bash not. Can you tell me more or point to some explanation? I do not want to add some modification blindly.
-
Mikkel about 8 yearsThis is the answer I was looking for, as I have separate GitHub accounts for home and work. I just had to set
Host work.github.com
HostName github.com
IdentityFile ~/.ssh/work
, and then replace "github.com" by "work.github.com" whenever I clone a work repository. It still connects to "github.com", but using a non-default key pair. -
gxx almost 8 yearsWOW! This is just great, didn't know about this. Thanks for the answer, quite helpful as well in puppet environments, to prevent the extra hassle to manage
.ssh/config
etc. +1! -
Nullpointer over 7 yearsUser git perfact
-
cr8ivecodesmith over 7 yearsExcellent answer! If you're using github, I made a quick guide about it: mattlebrun.com/use-different-git-ssh-key-per-project.html
-
eckes over 7 yearsthings have become even better: as of Git 2.10, you can store the command in your Git configuration: stackoverflow.com/a/38474220/520162
-
lessthanideal over 7 yearsNote you might not need "username" in your git path. e.g. my user on our local gitlab with permission for our shared project is Alice, I'm logged onto Linux as Bob. I created the ssh keys as Bob and put the public key on gitlab associated with Alice. Now I can clone like this from Linux, logged in as Bob, without mentioning "Alice" anywhere,
-
Daniele Testa over 7 yearsThis solution does not work together with the --recursive flag. The submodules are not fetched using the specified key and therefor fails if they require auth.
-
flaviovs over 7 yearsEach submodule is an entirely different repository, with their own set of remotes. They're glued together by Git for your convenience, but in no way remotes for a submodule are tied to the ones in the parent repository. I'm afraid that you must set the remote using the
ext
transport in each submodule for recursion in the parent to work. -
Noitidart about 7 yearsFor me I had to remove the ` -F /dev/null` i dont know why , otherwise it would tell me:
git config core.sshCommand "ssh -i ~/.ssh/toptal_i nterview_3_rsa -f /dev/null" PS C:\Users\Mercurius\Desktop\timekeep> git push -u origin master ssh: Could not resolve hostname /dev/null: Name or service not known
-
Flimm about 7 years@Noitidart
/dev/null
is only a valid filename in UNIX-like operating systems, it doesn't work on Windows. -
Noitidart about 7 yearsThanks very much @Flimm, so it is safe to do your command without the
-F
too? Also I don't understand in the second part, since 2.10.0 you mention we can configure it globally, but the second part only shows the local method no? -
weeJimmy about 7 yearsThe
core.sshCommand
config setting was just the thing I needed, because it lets me use a certain key by default in most circumstances, but then specify a different key with acore.sshCommand
in arepository/.git/config
file for a specific repo. Thank you! -
Mark almost 7 yearsIf you need multiple keys, the -i parameter can be repeated, and ssh will try each key in turn.
git config core.sshcommand "ssh -i /path/to/keyA -i /path/to/keyB"
. This lets git use different keys with different remote hosts. -
Laure almost 7 yearsOMG why wouldn't it just tell me that the rights are wrong... It said its wrong first (warned) and then I've changed it. It didn't tell me next time saying me just that permission is denied.
-
Daniel Dewhurst over 6 years
$ ssh-agent sh -c 'ssh-add ~/.ssh/id_rsa; git fetch user@host'
worked for me when nothing else would. Kudos. -
Carl Smotricz over 6 yearsThe URL for details ("itblog.study.land/...") doesn't work any more :(
-
Greg Dubicki over 6 yearsI had to use
~/.ssh/config
method, env vars didn't work for me... -
luator over 6 yearsFor git versions < 2.3, you can use
GIT_SSH
(see other answers). -
Dominik over 6 years
GIT_SSH
is available since v0.99.4 (August 2005), so basically since Git exists (April 2005). -
VasyaNovikov over 6 years@ValentinKlinghammer the answer from @Flimm has the solution for this question. It is to use
core.sshCommand
git configuration. superuser.com/a/912281/162466 -
Sprachprofi about 6 yearsYou saved my life! Been struggling with different work and private Github & Heroku credentials for hours!!
-
Gomino about 6 yearsIf you encounter the following error
fatal: transport 'ext' not allowed
, you have to whitelist the ext protocol via theexport GIT_ALLOW_PROTOCOL=ext
. Basically, the git-remote-ext remote helper (which supports "ext::ssh example.com %S foo/repo" URLs) allows arbitrary command execution. This normally isn't ever a concern because user always sees and trusts the URL they pass to git. However git submodules, through the .gitmodules file, allow an attacker to request the client to fetch arbitrary git URLs. hackerone.com/reports/104465 -
Scott - Слава Україні almost 6 yearsDid you notice that the question is about “a system with multiple private keys in the
~/.ssh
directory”? -
Cerin almost 6 yearsWhat is "git.example.com"? How would you use this with github or bitbucket, neither of which have a git.* subdomain?
-
Cerin almost 6 yearsThis doesn't work when trying it with bitbucket,
git clone 'ext::ssh -i /home/myuser/.ssh/id_rsa_customkey git.bitbucket.org %S repo/project.git'
=>Permission denied (publickey). fatal: Could not read from remote repository.
-
Cerin almost 6 yearsYou should remove the first half of your answer. No one's interested in a solution that doesn't work, and it's wasted reading that obfuscates the correct answer at the bottom, which works wonderfully.
-
flaviovs almost 6 years
git.example.com
is a placeholder host name. You must be able to ssh to the actual host for this to work, so I suggest you try ssh first using the specified key and get to the command line, double-check the actual path to the repository, and only then try to use theext
transport. -
Jan Vlcinsky almost 6 years@Cerin If you mean removing the "Error to avoid" I am going to keep it there. It shares common pitfall to avoid and it is very short. I am sure, someone would try optimizing the solution by providing all the things into variable (this happened to me), so I tried to shorten the path to success.
-
Ondra Žižka over 5 yearsThis is probably a good way, but my Git tries my default GitHub user, which has another key (GitHub wants unique-per-user keys). How can I make it use another user for other repo?
-
flaviovs over 5 years@OndraŽižka, you can add
-l USER
to the ssh command line to log in as userUSER
. -
nuno over 5 yearsThis worked for me - important to note that creating a directory inside
.ssh
and trying to organize keys inside directories would require to also change the permissions of that directory. -
Allan Andrade over 5 yearsThis was my mistake: "If you already have a remote set up...". Thanks a lot!!!
-
Tyler Collier over 5 yearsFor me
GIT_SSH_COMMAND
didn't work until I usedIdentitiesOnly
, such as this command:GIT_SSH_COMMAND="ssh -i ~/.ssh/mysubdir/id_rsa -o 'IdentitiesOnly yes'" git push
. -
thucnguyen over 5 years@CarlSmotricz the original one was moved here: medium.com/@thucnc/…
-
Mageician over 5 yearsFINALLY!!! This answer actually shows how you can utilize what you put in the
~/.ssh/config
file. Every other answer misses how you can set the host when you add the origin, which automatically allows git to use the correct key file. THANK YOU!! -
Goddard over 5 yearsnone worked for me...not sure why
-
Lucas D'Avila about 5 yearsNice, that was what I was looking :)
-
Srikrushna about 5 yearsPlease explain the process including How can I create an agent
-
Scott - Слава Україні about 5 years(1) Are you quoting somebody or something? If so, please identify the source. If not, please don’t use quote formatting. (2) What is “ed25519”? … … … … … … … … … … … Please do not respond in comments; edit your answer to make it clearer and more complete.
-
Goddard about 5 yearscommon mistake---this is the answer
-
eigenfield almost 5 yearsThis is the best answer. The use of the environment variable via
export GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_otherkey"
is so handy and flexible. I don't like setting multiple github keys in configuration.ssh/config
because I also have to alias the github url for example,github.com
becomesgithub.com.smeagol
just to differentiate and this alias URL becomes your git remote address. -
Cerin almost 5 yearsThis forces git to use a specific key for an entire domain, which usually won't work. For example, if someone has a personal github account as well as a work account, this configuration will break one of them.
-
Ding-Yi Chen over 4 yearsThis is especially useful when debugging git ssh. I can add -vvv to increase verbose mode.
-
Arka Prava Basu over 4 yearsHi !! Do you know how to propagate this to a submodule?
-
Ross about 4 yearsWon't work with GIT LFS
-
Zeth almost 4 yearsSounds smart, - but maybe a little to good to be true, considering how clumbsy all the other answers are. I couldn't get this to work.
-
JimmyJames over 3 yearsThis answer deserves way more upvotes.
-
Muhamed Huseinbašić over 3 yearsWhy are you adding the -F flag? To make sure no other config is used aside from the one explicitly mentioned?
-
Flimm over 3 years@MuhamedHuseinbašić Yes.
-
pwned over 3 yearsThis answer is outdated.
-
pwned over 3 yearsTgus answer is outdated.
-
kenorb over 3 years@pwned Which part?
-
pwned over 3 years@kenorb the part which doesn't suggest core.sshCommand
-
kas over 3 yearsThe user option is not required since you're passing the user in the git clone command.
-
Jinmiao Luo over 3 years@Zeth You may have a problem when creating the ssh agent. If you are using MacOS, you only need to execute
ssh-agent
. If you are using Linux, I suggest you read this article wiki.archlinux.org/index.php/SSH_keys#ssh-agent -
therobyouknow over 3 years+1 upvote great answer, it helped me also, I've used this and found this to work. 2 additional tips: 1) slightly different for bitbucket, repos are identified by project/repo-name, so my git
origin
looks like:git@therobyouknow:therobyouknow/myproject.git
(where the first therobyouknow is theHost
inconfig
and the 2nd therobyouknow is the bitbucket project. -
therobyouknow over 3 yearsTip 2) and essential: if you have other
Host *
also in your config, whereby you want to use that for all over remote machines, except for your gitlab/bitbucket/github, then you need to make sure you exclude that config fromHost *
and I did this by changingHost *
toHost !bitbucket.org
which meant that its config doesnt "bleed" into my bitbucket config. See My comment here to the original answer there I want to give credit for here for this idea -
therobyouknow over 3 yearsTo clarify Tip 2) further: from what I've found, it does the same job as
Host * !bitbucket.org
(which itself didn't work for me) but without the*
, so whatHost !bitbucket.org
(which did work for me) is saying is: "Host *
- everything except forbitbucket.org
" - the*
- meaning "everything", though absent, is still in effect and implied. -
Maddes over 3 yearsJust for your interest: A
Match Path
feature for OpenSSH would not help here, see marc.info/?l=openssh-unix-dev&m=141833748901966&w=2 -
Jakob over 3 yearsWith Windows that would be
-F nul
, but with OpenSSH one can use-F none
-
user905686 about 3 yearsRegarding contacting the same host with different keys: Here it is essential to understand that in
.ssh/config
Host
is a custom name you can give to the host specified underHostName
. Thegithub.com
part in the git URL[email protected]:torvalds/linux.git
refers to thisHost
and thus has to match it exactly. If you have a second Github ssh key, you can create a sectionHost github2
in.ssh/config
and then use the URLgit@github2:torvalds/linux.git
(see also superuser.com/a/1519694/96128). -
Aspiring Dev about 3 yearsThis is it. There's no git command hacks no nothing. This is it. Thank you.
-
Vadim almost 3 yearsBrilliant stuff.
-
Tony Park almost 3 yearsThis was particularly useful setting up a CICD pipeline that pulled multiple projects from github. Github insists on using a separate deploy key per project, and using these custom hosts is how I get the pipeline to use the right keys per project.
-
jherek almost 3 yearsThe full process is also documented on chasethedevil.github.io/post/github-and-ssh (which uses the same trick)
-
nick-s almost 3 yearsI spent hours looking for a solution and this was the easiest. Works like a charm for setting different ID files using a shell function by just setting the env var.
-
Toto over 2 yearsYou answer is really short for a very old question that has many documented answers.
-
Arnold Parge over 2 yearsUseful answer. In addition, in Mac
-F /dev/null
is not required. -
toryan over 2 yearsIf it was my question, I would mark this as the correct answer. Cheers!
-
Tyson Phalp over 2 yearsIncredible. Thanks for this--this worked for me, and felt the most straight-forward.
-
m8labs over 2 yearsOr just
git remote add origin git@personal:username/my-personal-project.git
-
shrimpwagon over 2 yearsThis is hands down the way to do it especially if you use deployment keys in Github
-
RicarHincapie over 2 yearsExcellent. I didn't wanted to remember to modify the default cloning string, so as
host
I set the same that appears in the original cloning string and works perfect and don't have to clone anything again. -
SamAko over 2 yearsGreat, this worked super well for me as I already had git config files for work and personal projects.
-
Coco over 2 yearsOr you can
git remote set-url origin git@personal:username/my-personal-project.git
for an existing project -
Adrian Herscu about 2 yearsTortoiseGit does not like this :(
-
nyxz about 2 years@AdrianHerscu I believe it should be fine if your TurtoiseGit uses the same SSH client as git. See the following answer stackoverflow.com/a/33328628/776546
-
Admin almost 2 yearsI have created an account just to upvote this...
-
Admin almost 2 yearsThis is the best and most flexible answer. +1