Christoffer
Christoffer

Reputation: 26865

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?

Upvotes: 1883

Views: 2139725

Answers (30)

Rouan van der Ende
Rouan van der Ende

Reputation: 97

I feel I have the most elegant solution. The problem for me is caused by having multiple github accounts and not being able to add the same key on multiple accounts.

So create a script somewhere like ~/scripts/gitssh.sh:

#!/bin/bash

ssh -i ~/.ssh/altkey/id_rsa $1 $2

Make it executable chmod +x gitssh.sh

Add a line to .bashrc

alias gitalt="GIT_SSH=~/scripts/gitssh.sh git"

Run a new terminal so it gets loaded and use it like normal git.

gitalt clone [email protected]:yourorganization/reponame.git

Upvotes: 0

Rafael Corrêa Gomes
Rafael Corrêa Gomes

Reputation: 1907

I just needed to add the key and then rerun the git clone.

ssh-add ~/.ssh/id_rsa_mynewkey
eval $(ssh-agent -s)
git clone [email protected]:mycompany/myrepo.git

Upvotes: 20

Ogada Stanley Chinedu
Ogada Stanley Chinedu

Reputation: 455

If you are getting an SSH permission denied Error when running commands like git push, pull, or fetch even after you have copied your SSH public key to GitHub.

NOTE
Use --local when you're in a local git repo,
but use --global when you want to apply to all repos

Use this:

git config --add --local core.sshCommand 'ssh -i /path-to-ssh-private-key'

E.g

git config --add --local core.sshCommand 'ssh -i /home/user/.ssh/github-key'

You're done!

Optionally you can verify your change with this:

git config --local --get core.sshCommand

Upvotes: 11

Alexandr S.
Alexandr S.

Reputation: 1804

In my case I've got two accounts with different ssh keys. I wanted to clone a repository, so how i did it:

id_ed25519 - is the name of second key, usually default key is: ~/.ssh/id_rsa

$ eval `ssh-agent -s`

$ ssh-add ~/.ssh/id_ed25519

If you use a Github you can check correct auth with command below:

$ ssh -T -p 443 [email protected]

Clone or Pull code with command below:

(for the first time)

$ git clone [email protected]:username/path-somewhere.git

(for the next time)

$ git pull

Upvotes: 3

HeyWatchThis
HeyWatchThis

Reputation: 23553

None of these solutions worked for me.

Instead, I elaborate on @Martin v. Löwis 's mention of setting a config file for SSH.

SSH will look for the user's ~/.ssh/config file. I have mine setup as:

Host gitserv
    Hostname remote.server.com
    IdentityFile ~/.ssh/id_rsa.github
    IdentitiesOnly yes # see NOTES below
    AddKeysToAgent yes

And I add a remote git repository:

git remote add origin git@gitserv:myrepo.git

(or clone a fresh copy of the repo with git@gitserv:myrepo.git as address)

And then git commands work normally for me.

git push -v origin master

If you have submodules, you can also execute the following in the repo directory, to force the submodules to use the same key:

git config url.git@gitserv:.insteadOf https://remote.server.com

NOTES

  • The IdentitiesOnly yes is required to prevent the SSH default behavior of sending the identity file matching the default filename for each protocol. If you have a file named ~/.ssh/id_rsa that will get tried BEFORE your ~/.ssh/id_rsa.github without this option.

  • AddKeysToAgent yes lets you avoid reentering the key passphrase every time.

  • You can also add User git to avoid writing git@ every time.

References

Upvotes: 1753

VonC
VonC

Reputation: 1328012

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

When cloning a new repo, where there is not yet any .git/config to modify, can first set it for just one command like git clone or git submodule add:

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

Once the repo exists you can set the option permanently in the .git/config:

cd <repo or submodule you just cloned>
git config core.sshCommand "ssh -i private_key_file"

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"

For all those commands, you can add a -o IdentitiesOnly=yes to limit SSH to the the private/public key you are specifying:

git config core.sshCommand 'ssh -i private_key_file -o IdentitiesOnly=yes' 
# or
git -c core.sshCommand="ssh -i private_key_file -o IdentitiesOnly=yes" clone host:repo.git
# or
set "GIT_SSH_COMMAND=ssh -i private_key_file -o IdentitiesOnly=yes"

gsullins suggests in the comments to adds to the .zshrc the following alias:

alias git.key1="git config core.sshCommand 'ssh -i <absolute path to private key>'"

As noted by Jaredo Mills in a comment:

One pitfall: if you mirror your repo to more than one host (Github, Gitlab), with different private keys, this method will send the wrong key.
The key is not associated with the repo, but with a username and hostname. ~/.ssh/config is the right place to get the association right, and it has the right matching capabilities for the job (see man ssh_config).

See HeyWatchThis's answer for illustration.

Upvotes: 431

Der Zinger
Der Zinger

Reputation: 555

Also, as a simple "workaround", if you don't really need it that often:

Remove all ssh identities from the currently running ssh agent (not physically).

ssh-add -D

Re-add the one you need to work with to your currently running ssh-agent

ssh-add ~/.ssh/MyProperProfile

Do the gits

Optionally - revert by adding other identities (or all of 'em).

Upvotes: 6

Madhavarao Kulkarni
Madhavarao Kulkarni

Reputation: 90

I was able to resolve this requirement with following command option to git clone --config core.sshCommand="ssh -i /d/repos/ssh/prod-a/.ssh/id_ed25519"

Upvotes: 1

Wojciech Domalewski
Wojciech Domalewski

Reputation: 280

Why don't you just add location of identity key to git config file for a particular repo like this:

cd .git

vi config

[core]
    sshCommand = ssh -i <IDENTITY_KEY_LOCATION> -o IdentitiesOnly=yes

That's all you need.

Upvotes: 10

lalo
lalo

Reputation: 929

Don't overcomplicate things, just use ssh-add to add a temporary identity

alias gpullpersonal='ssh-add mykey;git pull;ssh-add -D'
alias gpullprofessional='ssh-add myotherkey;git pull;ssh-add -D'

Upvotes: 0

Hix.botay
Hix.botay

Reputation: 433

Clone in one command

git -c core.sshCommand='ssh -i /path/to/key/' clone [email protected]:your_repository.git /path/target/clone --branch git_branch_name

Upvotes: 6

Flimm
Flimm

Reputation: 151201

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).

Upvotes: 47

codeVerine
codeVerine

Reputation: 762

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.

Upvotes: 3

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

Upvotes: 5

Gilbert
Gilbert

Reputation: 3334

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:

Dyson@dyson-ubuntu-vm:~/projects$ git init --bare s2

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

ssenyonjo@ssenyonjo-pc:~/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

Upvotes: 5

RicHincapie
RicHincapie

Reputation: 3993

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.

Upvotes: 69

Fattie
Fattie

Reputation: 12373

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

Upvotes: 19

J.T
J.T

Reputation: 579

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.

Upvotes: 42

Peyman Mahdavi
Peyman Mahdavi

Reputation: 179

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!

Upvotes: 5

Robert Jack Will
Robert Jack Will

Reputation: 11591

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 user@host: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.

Upvotes: 959

Mike Z.
Mike Z.

Reputation: 109

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:\Path\to\your\repo" pull && ssh-agent -k' 

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

Upvotes: 4

Anto Khan
Anto Khan

Reputation: 37

You can try sshmulti npm package for maintaining multiple ssh key.

Upvotes: -6

Rotem jackoby
Rotem jackoby

Reputation: 22208

A lot of good answers, but some of them assume prior administration knowledge.

I think it is important to explicitly emphasize that if you started your project by cloning the web URL - https://github.com/<user-name>/<project-name>.git
then you need to make sure that the url value under [remote "origin"] in the .git/config was changed to the SSH URL (see code block below).

With addition to that make sure that you add the sshCommmand as mentioned below:

user@workstation:~/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

Read more about it here.

Upvotes: 13

carlsborg
carlsborg

Reputation: 2939

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

Upvotes: 50

rodzmkii
rodzmkii

Reputation: 1577

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 git@XXX:myuser/myrepo.git
    >git remote -v
    origin  git@XXX:myuser/myrepo.git (fetch)
    origin  git@XXX:myuser/myrepo.git (push)
    

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

Upvotes: 116

cgnorthcutt
cgnorthcutt

Reputation: 4046

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.

Upvotes: 19

cristobal
cristobal

Reputation: 462

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.

Upvotes: 9

l3x
l3x

Reputation: 31246

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}" "$@"

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

Upvotes: 0

gajanan malvade
gajanan malvade

Reputation: 75

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

Upvotes: 1

Dan Dascalescu
Dan Dascalescu

Reputation: 151787

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>\.ssh\config) 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 git@github-work:company/project.git.

Upvotes: 167

Related Questions