How to specify an ssh-key file with the Git command

If you want to use an ssh-key file whenever you run the ssh command, one convenient way to do this is to use the -i option.


ssh -i ~/.ssh/thatuserkey.pem thatuser@myserver.com

This is pretty neat. It’s simple, elegant, and highly intuitive. I want to do the same thing with the Git command like this:


git -i ~/.ssh/thatuserkey.pem clone thatuser@myserver.com:/git/repo.git

Unfortunately, there is no such -i option in the git command. Bummer.

I’ve looked around but I can’t find a solution like this. There are two options I can think of: 1) use GIT_SSH and 2) use a wrapper script.

Option 1: Use the GIT_SSH environment variable

The GIT_SSH option will allow you to specify a key file with the Git command like this:


PKEY=~/.ssh/thatuserkey.pem git clone thatuser@myserver.com:/git/repo.git

where ~/.ssh/thatuserkey.pem is the keyfile you want to use.

To make this work, it needs some pre-configuration. The first step is to create a shell script that contains the following.

~/ssh-git.sh


#!/bin/sh
if [ -z "$PKEY" ]; then
# if PKEY is not specified, run ssh using default keyfile
ssh "$@"
else
ssh -i "$PKEY" "$@"
fi

The script needs to be executable so do a chmod +x on it.

Next step is to set the value of the GIT_SSH variable to the path of the script above. The variable will need to be exported to the shell environment.


export GIT_SSH=~/ssh-git.sh

Now every time you run the git command, the keyfile you set to the PKEY variable is passed to the shell script GIT_SSH is pointing to. This will then allow Git to connect using that key file.


PKEY=~/.ssh/thatuserkey.pem git clone thatuser@myserver.com:/git/repo.git

From hereon, every time you run the Git command, you can freely choose any key file you want to use by setting the PKEY variable.[1]

If you run the git command without the PKEY line, the GIT_SSH script will still run since this is exported to the shell environment. The script has a fail safe to avoid using the -i option if there was no keyfile set so that it can still run using the default keyfile.

Be careful when exporting PKEY to the shell environment because GIT_SSH will use whatever value it is set to even if you don’t specify it with the git command. This brings another problem with GIT_SSH exported to the environment since Git will always use this when it runs. So you need to be constantly conscious that you have this set. You can always chain the GIT_SSH setting with the git command to avoid exporting it to the environment, but at the expense making the entire command longer.

The PKEY-line usage works well except that the setting of PKEY together with the git command is somehow unconventional.[2]

If you find this unintuitive, there is another option.

Option 2: Use a wrapper script

The -i option with ssh is pretty neat and elegant. You supply the -i option to choose the key file you want to use. If you don’t use the option, ssh will fall back to use the default ssh-key file.

To use the -i option with the Git command, we need to write a wrapper script. The wrapper script will then allow us to set the usage we like and that is to mimic the -i option in ssh.

The usage will be something like this:


git.sh -i ~/.ssh/thatuserkey.pem clone thatuser@myserver.com:/git/repo.git

where git.sh is the wrapper script.

The only thing you need to do is create that script, put it in your PATH, and you’re all set.

To get the code, you can download it from here or cut-and-paste that below.

git.sh


#!/bin/bash

# The MIT License (MIT)
# Copyright (c) 2013 Alvin Abad

if [ $# -eq 0 ]; then
    echo "Git wrapper script that can specify an ssh-key file
Usage:
    git.sh -i ssh-key-file git-command
    "
    exit 1
fi

# remove temporary file on exit
trap 'rm -f /tmp/.git_ssh.$$' 0

if [ "$1" = "-i" ]; then
    SSH_KEY=$2; shift; shift
    echo "ssh -i $SSH_KEY \$@" > /tmp/.git_ssh.$$
    chmod +x /tmp/.git_ssh.$$
    export GIT_SSH=/tmp/.git_ssh.$$
fi

# in case the git command is repeated
[ "$1" = "git" ] && shift

# Run the git command
git "$@"

The wrapper script can fail gracefully. If you don’t specify the -i option, it will run git using your default key-file.

This wrapper script uses the same principle of the GIT_SSH environment variable. But instead of pre-setting this up manually, the wrapper script sets this up on the fly every time it runs the actual git command.

Other options

There are other ways to use different ssh-keys with the Git command. There is this $HOME/.ssh/config file where you can map different keys to hosts you want to connect to. But this method doesn’t allow you to choose any key file at will when you need to run the git command. The keys need to be pre-defined in the config file.

You can also use ssh-agent to programmatically add the key you want to use. I also wrote a wrapper script that uses ssh-agent to allow the -i option. But it turned out to be more complex than GIT_SSH way. I’ll probably post that to show how it can be done that way.

With all the different methods available, none is necessarily better than the other. It will all depend on the circumstances and of course your personal taste.

Alvin


[1] I prefer this kind of control in my workflow because I use different keys for different servers I use. I have a different key for my servers at work and different keys for my personal servers and public sites (like Github). It works the same with passwords. You don’t use the same password on your Facebook and bank accounts.


[2] Personally, I find this all right since I am used to this usage. I run a lot of scripts and make commands that require environment settings. But I don’t like the idea of exporting all of them to the shell environment and leaking them everywhere so I only specify them with the command.