Using git while on-the-run

First published: 07 Jul 2025

This post describes how to use a custom git configuration, including SSH and GPG keys, stored on a an external drive such as a USB stick. This is nothing fancy but comes in handy when the user does not want to store their keys persistently on the machine.

This setup originates from situations where I would like to work on my personal git repositories, yet I don't want to store my git configuration, my SSH key for authentication or my GPG key for signing commits on the device that I'm currently working with. This is for example often the case at work where I use a company laptop, virtual machines and servers on which I do not want my key material to persist on the system nor to conflict with the existing configuration.

This is of course intended for machines that are trusted enough to load key material onto. By no means I recommend plugin such a USB stick into non-trusted devices.

Generating and storing the secret keys

For those who haven't got working pairs of SSH and GPG keys already, I recommend looking up the best practices on generating them. The following resources are a good starting point:

I store my git configuration file, my SSH key used for git authentication, my GPG subkey to sign commits on LUKS filesystems that are unlocked by using a passphrase. Here is how I structure the files on them:

/mnt/usb/
├── alias.sh
├── git/
│   └── config
├── keys/
│   ├── gpg/
│   │   ├── public.asc
│   │   ├── public.gpg
│   │   ├── revocation.asc
│   │   ├── subkey.asc
│   │   └── subkey.gpg
│   └── ssh/
│       ├── skywhi_ed25519
│       └── skywhi_ed25519.pub
└── signing_keyring/
    ├── gpg.conf
    └── pubring.kbx

Working on a new device

The usage of environment variables, as opposed to aliases, will not only apply the new settings to git but will also propagate them throughout the shell session to other programs such as make and custom scripts. The environment variables that we will set are GIT_CONFIG_GLOBAL, GIT_SSH_COMMAND and GNUPGHOME.

  • GIT_CONFIG_GLOBAL tells git to use a custom configuration file,
  • GIT_SSH_COMMAND specifies the SSH command used by git to authenticate to remote repositories.
  • GNUPGHOME points towards a GPG keyring and configuration file used when git calls gpg to sign commits.
$ man git | grep -A1 'GIT_CONFIG_GLOBAL'
       GIT_CONFIG_GLOBAL, GIT_CONFIG_SYSTEM
           Take the configuration from the given files instead from global or
           system-level configuration files. If GIT_CONFIG_SYSTEM is set, the system
           config file defined at build time (usually /etc/gitconfig) will not be
           read. Likewise, if GIT_CONFIG_GLOBAL is set, neither $HOME/.gitconfig nor
           $XDG_CONFIG_HOME/git/config will be read. Can be set to /dev/null to skip
           reading configuration files of the respective level.


$ man git | grep 'GIT_SSH_COMMAND'
       GIT_SSH, GIT_SSH_COMMAND
           If either of these environment variables is set then git fetch and git push
           will use the specified command instead of ssh when they need to connect to
           a remote. The command-line parameters passed to the configured command are
           determined by the ssh variant. See ssh.variant option in git-config(1) for
           details.

           $GIT_SSH_COMMAND takes precedence over $GIT_SSH, and is interpreted by the
           shell, which allows additional arguments to be included.  $GIT_SSH on the
           other hand must be just the path to a program (which can be a wrapper shell
           script, if additional arguments are needed).

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


$ man gpg | grep -A1 'GNUPGHOME$'
       GNUPGHOME
              If set directory used instead of "~/.gnupg".

These environment variables are set and unset using shell functions defined in /mnt/usb/alias.sh:

setupgit() {

    local KEY_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )";

    # If the variable is already defined, make a backup before updating it and
    # export both.
    [[ ! -z ${GIT_CONFIG_GLOBAL+x} ]] && export BAK_GIT_CONFIG_GLOBAL=$GIT_CONFIG_GLOBAL
    export GIT_CONFIG_GLOBAL="${KEY_DIR}/git/config"

    [[ ! -z ${GIT_SSH_COMMAND+x} ]] && export BAK_GIT_SSH_COMMAND=$GIT_SSH_COMMAND
    export GIT_SSH_COMMAND="ssh -i ${KEY_DIR}/keys/ssh/skywhi_ed25519"

    [[ ! -z ${GNUPGHOME+x} ]] && export BAK_GNUPGHOME=$GNUPGHOME
    export GNUPGHOME="${KEY_DIR}/signing_keyring"
}

unsetupgit() {

    # If there is a backup of the variable, then restore the old value and
    # export it. Otherwise, clean the variable.
    [[ ! -z ${BAK_GIT_CONFIG_GLOBAL+x} ]] \
        && { export GIT_CONFIG_GLOBAL=${BAK_GIT_CONFIG_GLOBAL} ; export -n BAK_GIT_CONFIG_GLOBAL ; } \
        || export -n GIT_CONFIG_GLOBAL

    [[ ! -z ${BAK_GIT_SSH_COMMAND+x} ]] \
        && { export GIT_SSH_COMMAND=${BAK_GIT_SSH_COMMAND} ; export -n BAK_GIT_SSH_COMMAND ; } \
        || export -n GIT_SSH_COMMAND

    [[ ! -z ${BAK_GNUPGHOME+x} ]] \
        && { export GNUPGHOME=${BAK_GNUPGHOME} ; export -n BAK_GNUPGHOME ; } \
        || export -n GNUPGHOME
}

So whenever I need to do some git operations using the configuration files on the drive /dev/sdb, I use the following commands:

# Open and mount the LUKS-encrypted device /dev/sdb
$ sudo cryptsetup open /dev/sdb cool-pendrive
$ sudo mount /dev/mapper/cool-pendrive /mnt/usb

# Load the environment variables
$ . /mnt/usb/alias.sh
$ setupgit

# Do some git things...
$ git commit -m 'My commit'   # Will be signed with my GPG key
$ git push                    # And pushed with my SSH key

# Restore the environment and unmount the external drive
$ unsetupgit
$ sudo umount /mnt/usb
$ sudo cryptsetup close cool-pendrive

Top of the page - Sitemap -