How to specify the private SSH-key to use when executing shell command on Git?

Questions : How to specify the private SSH-key to use when executing shell command on Git?

A rather unusual situation perhaps, but I want to specify a private SSH-key to use when executing a shell (git) command from the local computer.

Basically like this:

git clone [email protected]:TheUser/TheProject.git -key "/home/christoffer/ssh_keys/theuser" 

Or even better (in Ruby):

with_key("/home/christoffer/ssh_keys/theuser") do sh("git clone [email protected]:TheUser/TheProject.git") end 

I have seen examples of connecting to a remote server with Net::SSH that uses a specified private key, but this is a local command. Is it possible?

Total Answers: 35 Answers 35


Popular Answers:

  1. Something like this should work (suggested by orip):

    ssh-agent bash -c 'ssh-add /somewhere/yourkey; git clone [email protected]:user/project.git' 

    if you prefer subshells, you could try the following (though it is more fragile):

    ssh-agent $(ssh-add /somewhere/yourkey; git clone [email protected]:user/project.git) 

    Git will invoke SSH which will find its agent by environment variable; this will, in turn, have the key loaded.

    Alternatively, setting HOME may also do the trick, provided you are willing to setup a directory that contains only a .ssh directory as HOME; this may either contain an identity.pub, or a config file setting IdentityFile.

  2. Something like this should work (suggested by orip):

    ssh-agent bash -c 'ssh-add /somewhere/yourkey; git clone [email protected]:user/project.git' 

    if you prefer subshells, you could try the following (though it is more fragile):

    ssh-agent $(ssh-add /somewhere/yourkey; git clone [email protected]:user/project.git) 

    Git will invoke SSH which will find its agent by environment variable; this will, in turn, have the key loaded.

    Alternatively, setting HOME may also do the trick, provided you are willing to setup a directory that contains only a .ssh directory as HOME; this may either contain an identity.pub, or a config file setting IdentityFile.

  3. Starting from Git 2.3.0 we also have the simple command (no config file needed):

    GIT_SSH_COMMAND='ssh -i private_key_file -o IdentitiesOnly=yes' git clone [email protected]:repo.git 

    Note the -o IdentitiesOnly=yes is required to prevent the SSH default behavior of sending the identity file matching the default filename for each protocol as noted in the answer above.

  4. Other people’s suggestions about ~/.ssh/config are extra complicated. It can be as simple as:

    Host github.com IdentityFile ~/.ssh/github_rsa 
  5. With git 2.10+ (Q3 2016: released Sept. 2d, 2016), you have the possibility to set a config for GIT_SSH_COMMAND (and not just an environment variable as described in Rober Jack Will‘s answer)

    See commit 3c8ede3 (26 Jun 2016) by Nguyễn Thái Ngọc Duy (pclouds).
    (Merged by Junio C Hamano — gitster in commit dc21164, 19 Jul 2016)

    A new configuration variable core.sshCommand has been added to specify what value for GIT_SSH_COMMAND to use per repository.

    core.sshCommand: 

    If this variable is set, git fetch and git push will use the specified command instead of ssh when they need to connect to a remote system.
    The command is in the same form as the GIT_SSH_COMMAND environment variable and is overridden when the environment variable is set.

    It means the git pull can be:

    cd /path/to/my/repo/already/cloned git config core.sshCommand 'ssh -i private_key_file' # later on git pull 

    You can even set it for just one command like git clone:

    git -c core.sshCommand="ssh -i private_key_file" clone host:repo.git 

    This is easier than setting a GIT_SSH_COMMAND environment variable, which, on Windows, as noted by Mátyás Kuti-Kreszács, would be

    set "GIT_SSH_COMMAND=ssh -i private_key_file" 
  6. Contents of my_git_ssh_wrapper:

    #!/bin/bash ssh -i /path/to/ssh/secret/key $1 $2 

    Then you can use the key by doing:

    GIT_SSH=my_git_ssh_wrapper git clone [email protected]:TheUser/TheProject.git 
  7. To sum up answers and comments, the best way to set up git to use different key files and then forget about it, which also supports different users for the same host (e.g. a personal GitHub account and a work one), which works on Windows as well, is to edit ~/.ssh/config (or c:Users<your user>.sshconfig) and specify multiple identities:

    Host github.com HostName github.com IdentityFile /path/to/your/personal/github/private/key User dandv Host github-work HostName github.com IdentityFile /path/to/your/work/github/private/key User workuser 

    Then, to clone a project as your personal user, just run the regular git clone command.

    To clone the repo as the workuser, run git clone [email protected]:company/project.git.

  8. As stated here: https://superuser.com/a/912281/607049

    You can configure it per-repo:

    git config core.sshCommand "ssh -i ~/.ssh/id_rsa_example -F /dev/null" git pull git push 
  9. The problem is when you have different remote repositories on the same host (say github.com), and you want to interact with them using different ssh keys (i.e. different GitHub accounts).

    In order to do that:

    1. First you should declare your different keys in ~/.ssh/config file.

      # Key for usual repositories on github.com Host github.com HostName github.com User git IdentityFile ~/.ssh/id_rsa # Key for a particular repository on github.com Host XXX HostName github.com User git IdentityFile ~/.ssh/id_other_rsa 

      By doing this you associate the second key with a new friendly name “XXX” for github.com.

    2. Then you must change the remote origin of your particular repository, so that it uses the friendly name you’ve just defined.

      Go to your local repository folder within a command prompt, and display the current remote origin:

      >git remote -v origin [email protected]:myuser/myrepo.git (fetch) origin [email protected]:myuser/myrepo.git (push) 

      Then change origin with:

      >git remote set-url origin [email protected]:myuser/myrepo.git >git remote -v origin [email protected]:myuser/myrepo.git (fetch) origin [email protected]:myuser/myrepo.git (push) 

      Now you can push, fetch… with the right key automatically.

  10. The fastest and simplest way of doing it is by:

    Clone your repo with ssh:

    git -c core.sshCommand="ssh -i ~/.ssh/<your_key>" clone [email protected]:<user>/<repo>.git

    then cd into you cloned repo and:

    git config core.sshCommand 'ssh -i ~/.ssh/<your_key>'

    To test it’s working:

    git --git-dir=/path/to/repo/.git pull

    So you may wonder: why my created ssh key does not work after I planted the .pub in github and the private is in the default directory?

    The documentation gives us a command that clarifies the issue: ssh -vT [email protected]

    The output shows a list of ssh keys names git looks for. So, you may want to create your key with one of those names, or use the above process to include the one you need.

  11. GIT_SSH_COMMAND="ssh -i /path/to/git-private-access-key" git clone $git_repo 

    or

    export GIT_SSH_COMMAND="ssh -i /path/to/git-private-access-key" git clone REPO git push 
  12. Way better idea to add that host or ip to the .ssh/config file like so:

    Host (a space separated list of made up aliases you want to use for the host) User git Hostname (ip or hostname of git server) PreferredAuthentications publickey IdentityFile ~/.ssh/id_rsa_(the key you want for this repo) 
  13. From Git version 2.10.0, you can configure this per repo or globally

    git config core.sshCommand "ssh -i ~/.ssh/id_rsa_example -o 'IdentitiesOnly yes'" 

    This will specify for the current repo what ssh key will use. I assume if you want to specify this global only need to set the --global option.

  14. I went with the GIT_SSH environment variable. Here’s my wrapper, similar to that from Joe Block from above, but handles any amount of arguments.

    File ~/gitwrap.sh

    #!/bin/bash ssh -i ~/.ssh/gitkey_rsa "[email protected]" 

    Then, in my .bashrc, add the following:

    export GIT_SSH=~/gitwrap.sh 
  15. 2021. If you’re on a Mac.

    Say you have an ubuntu server on aws, which you normally connect to like this:

    % ssh -i blah/yourkeypair.pem [email protected] 

    In terminal just

    % export GIT_SSH_COMMAND="ssh -i /Users/fattie/Desktop/blah/yourkeypair.pem" 

    After you have done that. You can then freely …

    % git clone [email protected]:/home/ubuntu/teste.git 

    That will clone the repo on your server to your local folder “teste”,

    you can then freely when in teste/ do the usual commands such as …

    % git push origin master 

    and so on.

    Note also: https://stackoverflow.com/a/67287133/294884


    As for on the server, it seems you basically

    ] git clone --bare the-actual-folder teste.git 

    and then in teste.git

    ] git init --bare --shared 
  16. If none of the other solutions here work for you, and you have created multiple ssh-keys, but still cannot do simple things like

    git pull 

    then assuming you have two ssh key files like

    id_rsa id_rsa_other_key 

    then inside of the git repo, try:

    # Run these commands INSIDE your git directory eval `ssh-agent -s` ssh-add ~/.ssh/id_rsa ssh-add ~/.ssh/id_rsa_other_key 

    and also make sure your github default username and userid are correct by:

    # Run these commands INSIDE your git directory git config user.name "Mona Lisa" git config user.email "[email protected]" 

    See https://gist.github.com/jexchan/2351996 for more more information.

  17. ssh-add ~/.ssh/id_rsa_mynewkey git clone [email protected]:mycompany/myrepo.git
  18. When you need to connect to github with a normal request (git pull origin master), setting the Host as * in ~/.ssh/config worked for me, any other Host (say, “github” or “gb”) wasn’t working.

    Host * User git Hostname github.com PreferredAuthentications publickey IdentityFile ~/.ssh/id_rsa_xxx 
  19. Many of these solutions looked enticing. However, I found the generic git-wrapping-script approach at the following link to be the most useful:
  20. [email protected]:~/workspace/project-name/.git$ cat config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true sshCommand = ssh -i ~/location-of/.ssh/private_key -F /dev/null <--Check that this command exist [remote "origin"] url = [email protected]:<user-name>/<project-name>.git <-- Make sure its the SSH URL and not the WEB URL fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master
  21. if you have directory on your path where you want to sign with a given identifyfile you can specify to use a specific identify file via the .ssh/config file by setting the ControlPath e.g.:

    host github.com ControlPath ~/Projects/work/** HostName github.com IdentityFile ~/.ssh/id_work User git 

    Then ssh will use the specified identity file when doing git commands under the given work path.

  22. This command clones the repo and configures the SSH key to use permanently:

    git clone -c "core.sshCommand=ssh -i ~/.ssh/<key>" [email protected]:<user>/<repo>.git 

    Now, if you run git fetch, git pull, or git push, it will use the SSH key configured in core.sshCommand (saved in .git/config).

  23. In Windows with Git Bash you can use the following to add a repository

    ssh-agent bash -c 'ssh-add "key-address"; git remote add origin "rep-address"' 

    for example:

    ssh-agent bash -c 'ssh-add /d/test/PrivateKey.ppk; git remote add origin [email protected]:test/test.git' 

    Which private key is in drive D, folder test of computer. Also if you want to clone a repository, you can change git remote add origin with git clone.

    After enter this to Git Bash, it will ask you for passphrase!

    Be Aware that openssh private key and putty private key are different!

    If you have created your keys with puttygen, you must convert your private key to openssh!

  24. The problem with this method is, at least when running by bash.exe on Windows, that it will create a new process every time which will remain dormant.

    ssh-agent bash -c 'ssh-add /somewhere/yourkey; git clone [email protected]:user/project.git' 

    If you want want to use that for syncig repo on schedule then you need to add “&& ssh-agent -k” at the end.

    Something like:

    ssh-agent bash -c 'ssh-add C:/Users/user/.ssh/your_key; git -C "C:Pathtoyourrepo" pull && ssh-agent -k' 

    ssh-agent -k will kill the process when it’s done.

  25. Most of the answers given here do not explain the details for the most basic usage.

    After you have setup a server (in this case a linux server) in the cloud, you connect to it using ssh from the terminal.

    From your computer, add the private key dyson-ubuntu-vm.pem which is given to you by your cloud services provider such as Azure, AWS etc to your .ssh configuration on your local machine like this:

    Copy the .pem file to the /home/ssenyonjo/.ssh folder, then open /home/ssenyonjo/.ssh/config file and add the following entry:

    Host 20.85.213.44 HostName 20.85.213.44 User Dyson IdentityFile /home/ssenyonjo/.ssh/dyson-ubuntu-vm.pem IdentitiesOnly yes 

    Now from your terminal, access the cloud linux server like so:

    ssh [email protected] 

    When that works, create a git project on the cloud server like so:

    [email protected]:~/projects$ git init --bare s2 

    Now come back to your local machine and clone that empty repository like so:

    [email protected]:~/Projects/mastering-git$ git clone ssh://[email protected]/home/Dyson/projects/s2 

    If you see an error that looks something like: fatal: Could not read from remote repository, It means you’re accessing the wrong folder. Ensure you have outlined the right path from the root to the created repository.

    If you dont want to setup a config file but want to access the ssh server that requires a key, you can use below command:

    GIT_SSH_COMMAND='ssh -i ~/Projects/aws/keys/aws_ubuntu.pem' git clone ssh://[email protected]/home/ubuntu/projects/mastering-git/rand 

    You can export the command to continue using it for other tasks like git push and git pull

    export GIT_SSH_COMMAND='ssh -i ~/Projects/aws/keys/aws_ubuntu.pem' 

    See: https://stackoverflow.com/a/29754018/10030693

  26. To have GIT_SSH_COMMAND environment variable work under Windows(CMD) instead of:

    set GIT_SSH_COMMAND="ssh -i private_key_file" 

    Use:

    set "GIT_SSH_COMMAND=ssh -i private_key_file" 

    The quote has to be like

    set "variable=value" 

    Some backgorund: https://stackoverflow.com/a/34402887/10671021

  27. You need to create a ~/.ssh/config as below

    Host <Your bitbucket server> User <userid> Hostname <Your bitbucket server as above> IdentitiesOnly yes IdentityFile ~/.ssh/id_rsa<file> This is your private key file 

    permission as below

    -rw------- $HOME/.ssh/config 

    Add your public key into your git (cat ~/.ssh/id_rsa_pub [or simillar name])

    and then git clone as below

    git clone ssh://[email protected]/userid/test.git 
  28. This is an extension to @VonC’s answer. Please read it first.

    Use case is I need to use both personal and work GitHub accounts using SSH. I want to use work SSH key as default as my projects will internally have other work repos as dependency. So cloning them should work seamlessly.

    Steps I followed are:

    • Generate default SSH key and add it to work git account.

    • Generate personal SSH key in a separate file and add it to personal git account.

    • Add the following function code in your .bashrc or .zshrc file and source it.

       gclone() { # Clone the repo-url using personal ssh-key git -c core.sshCommand="ssh -i path_to_personal_key" clone "$1" && # Extract repo name from URL using "awk" and switch to that folder using "cd"  cd $(awk '{ sub(/.*//, ""); sub(/.git.*/, ""); print }' <<< "$1") && # Set personal ssh-key as default for this repo  git config core.sshCommand "ssh -i path_to_personal_key"; } 
    • Use gclone command to clone repos using personal SSH key and set the repo to use that key as default.

    • Use normal git clone command to clone repos with default(work) SSH key.

  29. You could use GIT_SSH environment variable. But you will need to wrap ssh and options into a shell script.

    See git manual: man git in your command shell.

  30. I use zsh and different keys are loaded to my zsh shell’s ssh-agent automatically for other purposes (i.e. access to remote servers) on my laptop. I modified @Nick’s answer and I’m using it for one of my repos that needs to be refreshed often. (In this case it’s my dotfiles which I want same and latest version across my all machines, wherever I’m working.)

    bash -c 'eval `ssh-agent`; ssh-add /home/myname/.dotfiles/gitread; ssh-add -L; cd /home/myname/.dotfiles && git pull; kill $SSH_AGENT_PID' 
    • Spawn an ssh-agent
    • Add read-only key to agent
    • Change directory to my git repo
    • If cd to repo dir is successful, pull from remote repo
    • Kill spawned ssh-agent. (I wouldn’t want many of agents lingering around.)
  31. for the gitlab RSAAuthentication yes

    Host gitlab.com RSAAuthentication yes IdentityFile ~/.ssh/your_private_key_name IdentitiesOnly yes 

    doc is here

  32. If SSH port number is not 22(default), add Port xx in ~/.ssh/config

    In my case (synology),

    Host my_synology Hostname xxxx.synology.me IdentityFile ~/.ssh/id_rsa_xxxx User myname Port xx 

    Then clone using Host title in config. (“my_synology”. to avoid @chopstik ‘s “*”)

    git clone my_synology:path/to/repo.git 
  33. If you’re like me, you can:

    • Keep your ssh keys organized

    • Keep your git clone commands simple

    • Handle any number of keys for any number of repositories.

    • Reduce your ssh key maintenance.

    I keep my keys in my ~/.ssh/keys directory.

    I prefer convention over configuration.

    I think code is law; the simpler it is, the better.

    STEP 1 – Create Alias

    Add this alias to your shell: alias git-clone='GIT_SSH=ssh_wrapper git clone'

    STEP 2 – Create Script

    Add this ssh_wrapper script to your PATH:

    #!/bin/bash # Filename: ssh_wrapper if [ -z ${SSH_KEY} ]; then SSH_KEY='github.com/l3x' # <= Default key fi SSH_KEY="~/.ssh/keys/${SSH_KEY}/id_rsa" ssh -i "${SSH_KEY}" "[email protected]" 

    EXAMPLES

    Use github.com/l3x key:

    KEY=github.com/l3x git-clone https://github.com/l3x/learn-fp-go 

    The following example also uses the github.com/l3x key (by default):

    git-clone https://github.com/l3x/learn-fp-go 

    Use bitbucket.org/lsheehan key:

    KEY=bitbucket.org/lsheehan git-clone [email protected]:dave_andersen/exchange.git 

    NOTES

    Change the default SSH_KEY in the ssh_wrapper script to what you use most of the time. That way, you don’t need to use the KEY variable most of the time.

    You may think, “Hey! That’s a lot going on with an alias, a script and some directory of keys,” but for me it’s convention. Nearly all my workstations (and servers for that matter) are configured similarly.

    My goal here is to simplify the commands that I execute regularly.

    My conventions, e.g., Bash scripts, aliases, etc., create a consistent environment and helps me keep things simple.

    KISS and names matter.

    For more design tips check out Chapter 4 SOLID Design in Go from my book: https://www.amazon.com/Learning-Functional-Programming-Lex-Sheehan-ebook/dp/B0725B8MYW

    Hope that helps. – Lex

  34. Here’s the ssh key hack i found while finding solution to this problem:

    For example you have 2 different set of keys:

    key1, key1.pub, key2, key2.pub

    Keep these keys in your .ssh directory

    Now in your .bashrc or .bash_profile alias file, add these commands

    alias key1='cp ~/.ssh/key1 id_rsa && cp ~/.ssh/key1.pub id_rsa.pub'

    alias key2='cp ~/.ssh/key2 id_rsa && cp ~/.ssh/key2.pub id_rsa.pub'

    Voila! You have a shortcut to switch keys whenever you want!

    Hope this works for you.

Tasg: git, bash