How to specify which SSH key to use within git for git push in order to have gitorious as a mirror?

The answer is to be found in the git reference manual.

GIT_SSH

If this environment variable is set then git fetch and git push will use this command instead of ssh when they need to connect to a remote system. The $GIT_SSH command will be given exactly two arguments: the username@host (or just host) from the URL and the shell command to execute on that remote system.

To pass options to the program that you want to list in GIT_SSH you will need to wrap the program and options into a shell script, then set GIT_SSH to refer to the shell script.

Usually it is easier to configure any desired options through your personal .ssh/config file. Please consult your ssh documentation for further details.

So, I need to write a wrapper script, I write this push-gitorious.sh script:

#!/bin/sh


if [ "run" != "$1" ]; then
  exec ssh -i "$GITORIOUS_IDENTITY_FILE" -o "StrictHostKeyChecking no" "$@"
fi

remote=YOUR_SSH_GITORIOUS_URL

echo "Mirroring to $remote"

export GITORIOUS_IDENTITY_FILE="`mktemp /tmp/tmp.XXXXXXXXXX`"
export GIT_SSH="$0"

cat >"$GITORIOUS_IDENTITY_FILE" <<EOF
YOUR SSH PRIVATE KEY

EOF
cat >"$GITORIOUS_IDENTITY_FILE.pub" <<EOF
YOUR SSH PUBLIC KEY

EOF

#echo git push --mirror "$remote"
git push --mirror "$remote"

rm -f "$GITORIOUS_IDENTITY_FILE"
rm -f "$GITORIOUS_IDENTITY_FILE.pub"

exit 0

Of course, you have to fill in the private key (the public key is included in the script for reference only. You also need to fill in the gitorious URL.

In the post-receive hook, you have to put:

path/to/push-gitorious.sh run

The run option is important, otherwise it will run ssh directly.

Warning: no checking is done on the remote host identity. You can remove the option from the ssh command line and customize known_hosts if you want to. In this use case, I don't think it's important.


The are two methods I know so that you can specify any keyfile you want to use for a git site at the git command line. You don't need to hard-code this keyfile in a config file or script. You simply supply this straight at the git command line.

Method 1: Use the GIT_SSH environment variable

The usage will be like this at the command line:

$ PKEY=~/.ssh/keyfile.pem git clone [email protected]:me/repo.git

To use this command, you need to do some pre-setup. First, create a shell script with the following contents:

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

Next, export and set the GIT_SSH variable with a value equal to the location of the shell script above.

$ export GIT_SSH=~/ssh-git.sh

where ~/ssh-git.sh is the filename of the shell script above.

The script must be executable so do a chmod:

$ chmod +x ~/ssh-git.sh

Now you can run this command with any keyfile you choose to use:

$ PKEY=~/.ssh/keyfile1.pem git clone [email protected]:me/repo.git

To use another keyfile for a different host:

$ PKEY=~/.ssh/keyfile2.pem git clone [email protected]:other/repo.git

This supports any keyfile you want to use. Every time you need to run git with a keyfile you want to use you, just supply it to the PKEY variable. You can forget everything else as long as the GIT_SSH has been pre-configured.

Take note of the PKEY variable. You may use any name as long as it matches what is used in the shell script GIT_SSH is pointing to.

Method 2: Use a wrapper script

The usage of the wrapper script will be something like this:

$ git.sh -i ~/.ssh/keyfile.pem clone [email protected]:me/repo.git

This usage is intuitive since it looks like running ssh with the -i option.

This doesn't require pre-setup of a shell script and GIT_SSH. You only need to download and run this single wrapper script with the git command.

You can get a copy of this wrapper script here: http://alvinabad.wordpress.com/2013/03/23/how-to-specify-an-ssh-key-file-with-the-git-command/


A simpler alternative which does not involve any external scripts is to use a SSH alias. I know the original poster asked specifically not to change ~/.ssh/config, but I suspect there is a misunderstanding here.

The local user on the server is not the same as the person doing the commit and can be a different person than the one doing the 'git push'.

  • on the server the hosting software can run as a single user (usually 'git')
  • the identity of the person doing the commit is only git's buisness (to add to commit's meta data), is irrelevant for the server and is not subject to authentication on the server
  • the identity of the 'git push'-er is relevant and is established on systems running the git hosting software on the server based on the ssh key

For this reason, on the system doing the push one can force a specific identity even for the same local account and the same remote server, even within the same git repository by using an ssh alias following using the method explained below.

Assume you have on the gitorious.org server your regular account, let's call it 'developer'. You don't want to automatically push using your 'developer' account [1], so you create another gitorious account for the sync, let's call it 'robot'.

For automation only the 'robot' account will be used:

Step 1: Add 'robot' to the gitorius project which needs to be pushed to.

Step 2: On the local machine create a paswordless key (this will be associated with the robot account on gitorious).

ssh-keygen -f ~/.ssh/id_rsa_robot

Step 3: upload the public key ~/.ssh/id_rsa_robot.pub on gitorious in the 'robot' account.

Step 4: The git SSH URIs on gitorious have the format git@gitorious.org:prj_or_user/subproject.git. In your ~/.ssh/config file add the following lines:

host robot.gitorious.org
        HostName gitorious.org
        IdentityFile ~/.ssh/id_rsa_robot
        IdentitiesOnly "yes"

This will make sure that:

  • whenever your use the 'robot.gitorious.org' hostname it will connect to gitorious.org (HostName option),
  • it will use the passwordless key to authenticate as robot on gitorius.org (IdentiFile option) and
  • even if you have a ssh agent running, it will ignore the default key and use the passwordless one (IdentiesOnly "yes").

Step 5: Assuming the SSH URI on gitorious for your project is '[email protected]:project/project.git', in the local repository define a new remote 'autopush' with a slightly modified host name:

git remote add autopush [email protected]:project/project.git

The setup is done, now try to push to gitorious via the 'autopush' remote.

git push autopush master

If everything went well and there are changes to push, you should see you succesfully pushed to 'gitorious.org' as 'robot'

[1] For automatic pushes a passwordless key must be generated for the account, but attaching it to the gitorious 'developer' account would mean that the automated job can push to any of the gitourious projects where 'developer' is involved on gitorious.