DEV Community

Cover image for Git: The complete guide to sign your commits with an SSH key
Christophe Colombier
Christophe Colombier

Posted on • Edited on

Git: The complete guide to sign your commits with an SSH key

Please read the introduction I wrote about why signing your git commits

To configure Git to sign commits with SSH keys, follow these steps:

Ensure Compatibility

Make sure you have Git version 2.34 or later, as SSH signature verification is available from this version onwards.

To check your git version, you can run the following command.



$ git --version
git version 2.43.2


Enter fullscreen mode Exit fullscreen mode

You also need OpenSSH 8.8 or newer. Signing is available since version 8.1, but was broken with 8.7. So version 8.8 or newer is recommended.

To check your ssh version, you can run the following command



$ ssh -V
OpenSSH_8.9 ...


Enter fullscreen mode Exit fullscreen mode

Generate or Use an Existing SSH Key

If you don't already have an SSH key, generate a new one. You can use an existing SSH key for signing commits and tags. The recommended types for the SSH key are ED25519 or RSA 2.

Configure Git to Use SSH for Signing:

Set Git to use SSH for signing by running the following command:



git config --global gpg.format ssh


Enter fullscreen mode Exit fullscreen mode

Commit signing was historically available with GPG. Git configuration evolved to use ssh format. It explains the strange setting about gpg.format=ssh

Specify the public SSH key to use as the signing key. Replace /PATH/TO/.SSH/KEY.PUB with the actual path to your public key:



git config --global user.signingkey /PATH/TO/.SSH/KEY.PUB


Enter fullscreen mode Exit fullscreen mode

For example, if your key is located at ~/.ssh/id_ed25519.pub, the command would be:



git config --global user.signingkey ~/.ssh/id_ed25519.pub


Enter fullscreen mode Exit fullscreen mode

You may see how telling you to add the

To verify SSH signatures locally, you'll need to create an allowed signers file and configure Git to use it.

You can choose to configure this globally, for example:



echo "$(git config --get user.email) namespaces=\"git\" $(cat ~/.ssh/id_ed25519.pub)" >> ~/.ssh/allowed_signers


Enter fullscreen mode Exit fullscreen mode

You can now tell git to use this file when checking your keys.



git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers


Enter fullscreen mode Exit fullscreen mode

Sign Commits

To sign a commit, use the -S flag with the git commit command:



git commit -S -m "Your commit message"


Enter fullscreen mode Exit fullscreen mode

Remember, Git uses the private key for signing. If your configuration uses a public key, Git will ask for the private key from the ssh-agent

So from now, every single commit you made are signed.

Sign Tags



git tag -s <whatever>


Enter fullscreen mode Exit fullscreen mode

Here you can see the tag signing using -s while git commit uses -S. git commit -s is used for something else the "signoff" thing.

Automatically Sign Commits && Tags

If you prefer not to use the sign flag every time, you can configure Git to automatically sign your commits and tags



git config --global commit.gpgsign true
git config --global tag.gpgsign true


Enter fullscreen mode Exit fullscreen mode

Verify Commits: Ensure that your commits are verified.

Signature verification uses the allowed_signers file to associate emails and SSH keys. For help to configure this file, refer to the documentation on verifying commits locally.



git log --show-signature


Enter fullscreen mode Exit fullscreen mode

About Signoff

You need to use --signoff with Git when:

  • You are contributing to a project that requires a Developer Certificate of Origin (DCO) for commits. The DCO is a statement that you have the right to submit the work under the same license as the project and that you are doing so under that license. The --signoff option adds a Signed-off-by: line at the end of the commit message, indicating that you certify the DCO.

  • You are working in a repository where the commit signoff policy is enabled, requiring users to automatically sign off on the commits they make. This can be managed through GitHub's web interface, where organization owners and repository admins can enforce this requirement.

The --signoff option is particularly useful in open-source projects to ensure that contributions are properly attributed and that the project's license is adhered to. It also helps in tracking who did what in the project, especially when patches are involved.

You can add a setting to automatically sign off your commit when they are signed



git config --global format.signoff true


Enter fullscreen mode Exit fullscreen mode

TL; DR;



git config --global gpg.format ssh
git config --global user.signingkey ~/PATH/TO/.SSH/KEY.PUB
echo "$(git config --get user.email) namespaces=\"git\" $(cat ~/PATH/TO/.SSH/KEY.PUB)" >> ~/.ssh/allowed_signers
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
git config --global commit.gpgsign true
git config --global tag.gpgsign true
git config --global format.signoff true


Enter fullscreen mode Exit fullscreen mode

In the next article, I will explain how to configure GitHub to display the "verified" badge aside your commits

Top comments (5)

Collapse
 
kinghat profile image
kinghat • Edited

inside a devcontainer vscode is forwarding the host ssh agent socket so you can push to repos via ssh. your actual key isnt on the containers filesystem. if i do: $ ssh -v git@github.com you can see that it cant find any keys and goes to the agent and uses the key it finds there. is it possible to tell gitconfig user.signingkey to use that?

i guess you can use the actual string value of your key in place of its path, could you do something like: git config --global user.signingkey ${ssh-add -L}

Collapse
 
ccoveille profile image
Christophe Colombier

I'm unsure what you meant. But my keys are protected with passphrase and I have to add them with the ssh agent to be able to commit otherwise it reports an error

Collapse
 
kinghat profile image
kinghat

the single key i have on my host is password protected as well. i have it unlocked and added to the agent when logging into my system. what im mostly wondering is if theres a way for the gitconfig to dynamically get your key? when doing this in a devcontainer your keys arent brought into the container, the agent socket is. so it seems like my only option is to set gitconfig with the key as a string to user.signingkey vs using the keys path because the key doesnt exist.

Thread Thread
 
ccoveille profile image
Christophe Colombier

You are right. I missed the point.

So yes, the signingKey can be provided as a string.

It's what I did months ago. I forgot I wrote my article pointing out the usage of a file.

Tell me if you need the syntax for using the key as a string.

Thread Thread
 
kinghat profile image
kinghat

i am using it as a string just fine, what im wondering is if you can set it dynamically. can git config pull the key from the agent? is git config parsed on every git command run? something like this:

[user]
        name = username
        email = useremail@emailhost.com
        signingkey = ${ssh-add -L}
Enter fullscreen mode Exit fullscreen mode