Reputation: 3811
I have 2 Git servers that require 2 different SSH keys.
git clone user1@server1:blahblahblah
uses ~/.ssh/id_rsa
, but I need to specify which key to use depending on the server I am connecting to.
What Git command-line parameter does this job? (I am running Linux.)
Upvotes: 163
Views: 169687
Reputation: 5930
You can use --global
or --local
configuration, global will update ~/.gitconfig
file, local will update configuration in the repository .git/config
and override the global (~/.gitconfig
) configuration
git config --local --add core.sshCommand 'ssh -i ~/.ssh/my_key'
Upvotes: 21
Reputation: 32354
[Update]: see my other answer for a configuration-based method with a ready-made script for you to use
In my scenario, similar to @Richard Smith scenario (whose solution, BTW, didn't work for me), I need to use different keys for the same server under different repositories.
The workaround for me was to set up the session correctly with the environment variable GIT_SSH_COMMAND
, like so:
export GIT_SSH_COMMAND="ssh -o IdentitiesOnly=yes -i ~/.ssh/my-secret-identitiy"
Update:
Another thing to note here is that setting the environment variable correctly can be a hustle, so I'm using the command prompt modification facilities provided by things like Liquid Prompt or Fish Shell to hook into the shell and keep updating the environment variables according to the current directory and some rules. For example, all my personal projects that need to my personal SSH key with Gitlab are under ~/Documents/Projects/personal
so when the shell hook runs pwd
and finds that the current directory is under that path, it automatically sets the GIT_SSH_COMMAND
variables as needed.
Upvotes: 30
Reputation: 32354
Another option is to write a small script to make core.sshCommand
a bit smarter - check if the current working directory has a specific SSH key configured and if so use it, otherwise - rely on the standard SSH key resolution.
Here is my first version:
#!/bin/bash
key="$(git config ssh.key)"
if [ -n "$key" ]; then
ssh -o IdentitiesOnly=yes -i "$key" "$@"
else
ssh "$@"
fi
Then set it up as the global git SSH command:
chmod 755 ~/.local/bin/git-ssh-command
git config --global core.sshCommand ~/.local/bin/git-ssh-command
(~/.local/bin
is the current standard for "place user scripts here" on SystemD operating systems)
After you set this up, you can configure any repository to use a specific SSH key by setting the configuration option ssh.key
:
git config --local ssh.key ~/.ssh/my-non-default-private-key
ssh.key
to have a "default fallback to non-default SSH key" or something.core.sshCommand
in the root directory of the repository, your custom git-ssh-command
can look at that and have some heuristics about directory names. This can be done in the else
section so heuristics only kick in if there is no specific key in ssh.key
.git remote -v
check to add heuristics based on the the remotes, like in Eike's scriptremote="$1:$(sed "s,.* ,,;s,',,g"<<<"$2")"
at the beginning of the script to resolve the remote being operated on - and check against that ($remote
would look like the middle column in git remote -v
output).Here's a version of the custom SSH command that looks at the remote URL and does some heuristics - in my case, I have several different identities with the same public git hosting service (one for work, one for personal, etc) and I can select the correct identity by looking at the remote URL (examining the Gitlab group or the Github organization, etc):
#!/bin/bash
while ! [[ "$1" =~ "git@" ]]; do shift; done # git may send ssh options
if [[ "$2" =~ ^git-lfs-authenticate.* ]]; then # reconstruct url for git-lfs
remote="$1:$(awk '{print$2}'<<<"$2")"
else # reconstruct url for standard git commands
remote="$1:$(sed "s,.* ,,;s,',,g"<<<"$2")"
fi
echo "Detected $remote from $@" >&2
key="$(git config ssh.key)"
if [ -n "$key" ]; then # use specified SSH key, if set
ssh -o IdentitiesOnly=yes -i "$key" "$@"
elif [[ "$remote" == [email protected]:my-company* ]]; then # use company id
ssh -o IdentitiesOnly=yes -i ~/.ssh/company-id "$@"
elif [[ "$remote" =~ [email protected]:.*other-org.* ]]; then # bitbucket has weird urls
ssh -o IdentitiesOnly=yes -i ~/.ssh/custom-org-key "$@"
else # otherwise use whatever the agent has (my personal key)
ssh "$@"
fi
Upvotes: 5
Reputation: 409
The other answers inspired me to write a little script that chooses the ssh key depending on command line options or (if present) the values of git remote -v. Hope it helps!
To actually answer the question: Use gat.
See also https://bitbucket.org/eikerobert/gat/src/master/
#!/bin/bash
usegat=false
for VAR in "$@"
do
if [ "$VAR" != "${VAR/[email protected]:myaccount/}" ]; then
usegat=true
fi
done
if [ $usegat=false ]; then
/usr/bin/git rev-parse --is-inside-work-tree >/dev/null 2>&1
isinsidegitrepo=$?
#echo $isinsidegitrepo
if [ $isinsidegitrepo = 0 ]; then
remote=`/usr/bin/git remote -v`
if [ "$remote" != "${remote/[email protected]:myaccount/}" ]; then
usegat=true
fi
fi
fi
if [ $usegat = true ]; then
# echo "TRUE"
/usr/bin/git -c core.sshCommand="/usr/bin/ssh -i /home/myaccount/.ssh/mykey" "$@"
else
#echo "FALSE"
/usr/bin/git "$@"
fi
Upvotes: 1
Reputation: 3454
There is another possibility. That's to set core.sshCommand
, e.g.
git config --local core.sshCommand "/usr/bin/ssh -i /home/me/.ssh/id_rsa_foo"
There's one particular scenario when this strategy is particularly useful: that's when you have multiple accounts on Github, as all accounts ssh
to Github as [email protected]
and it uses the ssh
key to determine which Github user you are. In this case neither .ssh/config
nor ssh-agent
will do what you want.
Update — You cannot run the above until you have a local repository, so if you're trying to clone a remote repository, you'll need to specify the key manually as per drewbie18's answer:
git clone -c core.sshCommand="/usr/bin/ssh -i /home/me/.ssh/id_rsa_foo" [email protected]:me/repo.git
Once you've cloned the repository you can use the git config
command to set this permanently.
Upvotes: 250
Reputation: 331
Windows user here, I just ran into this issue and have a slightly different solution then I have read here so far. The problem I faced is that I simply wanted to clone a repo using a specific private ssh key and not have to globally configure my git config or add specific git bash settings, as I do my work in PowerShell. Essentially I just want to have some private keys sitting in my .ssh folder and I reference them in specific repos as required.
The following command works for this:
git clone -c core.sshCommand="ssh -i ~/.ssh/<PRIVATE KEY NAME>" <CLONE URL>
Essentially what this does is upon the initialization of the git repo it sets the core.sshCommand option before running the clone. So the specific ssh key you wish to use for this repo is set ONLY for this repo. This may not be an ideal solution for all cases but for what I want it is.
Upvotes: 14
Reputation: 54376
If you are connecting via SSH then the key will be controlled by an SSH parameter, not a git parameter.
SSH looks in the ~/.ssh/config
file for configuration parameters. Modify that file and add IdentityFile entries for the two Git servers like this:
Host server1.whatever.com
IdentityFile /path/to/key_1
Host server2.whatever.com
IdentityFile /path/to/key_2
This article has some more details.
Upvotes: 99
Reputation: 48799
Generally, you want to use ~/.ssh/config
for this. Simply pair server addresses with the keys you want to use for them as follows:
Host github.com
IdentityFile ~/.ssh/id_rsa.github
Host heroku.com
IdentityFile ~/.ssh/id_rsa.heroku
Host *
IdentityFile ~/.ssh/id_rsa
Host *
denotes any server, so I use it to set ~/.ssh/id_rsa
as the default key to use.
Upvotes: 55