Git commit signing is a powerful way to verify the authenticity of code changes, ensuring that commits are indeed from the person they claim to be.
Let’s see it in action. First, you need a GPG key. If you don’t have one, generate it:
gpg --full-generate-key
Follow the prompts. For commit signing, a 4096-bit RSA key is a good choice. Once generated, list your keys to find the key ID:
gpg --list-secret-keys --keyid-format LONG
You’ll see something like:
sec rsa4096/YOUR_KEY_ID_LONG 2023-10-27 [SC]
YOUR_KEY_FINGERPRINT
uid [ultimate] Your Name <your.email@example.com>
ssb rsa4096/ANOTHER_KEY_ID 2023-10-27 [E]
The YOUR_KEY_ID_LONG is what you’ll use. Now, tell Git to use this key for signing:
git config --global user.signingkey YOUR_KEY_ID_LONG
Next, configure Git to sign commits by default. You can do this globally or per-repository:
git config --global commit.gpgsign true
Now, when you make a commit:
git commit -m "Add amazing new feature"
Git will prompt you for your GPG passphrase (if you set one) and then create a signed commit. You can verify this by looking at the log:
git log --show-signature
You’ll see output like:
commit abcdef1234567890...
gpg: Signature made Mon 30 Oct 2023 10:00:00 AM UTC
gpg: using RSA key YOUR_KEY_ID_LONG
gpg: Good signature from "Your Name <your.email@example.com>" [ultimate]
Author: Your Name <your.email@example.com>
Date: Mon Oct 30 10:00:00 AM UTC 2023 +0000
Add amazing new feature
To enable others to verify your signatures, you need to upload your public key to a keyserver. First, export your public key:
gpg --armor --export YOUR_KEY_ID_LONG > my_public_key.asc
Then, upload it:
gpg --keyserver hkps://keys.openpgp.org --send-keys YOUR_KEY_ID_LONG
Now, anyone can import your key and verify your commits.
The core problem commit signing solves is the "man-in-the-middle" attack on your commit history. Without signing, anyone who can push to your repository could potentially forge commits, making it impossible to trust who actually wrote what. With signing, you establish a cryptographic link between a specific identity (your GPG key) and your commits. This allows for robust auditing, accountability, and trust within a development team, especially in open-source projects where contributors are often anonymous. It’s not just about preventing malicious actors; it’s about building a verifiable history that everyone can rely on.
When you sign a commit, Git doesn’t just attach your public key. It creates a detached signature using your private key. This signature is a cryptographic hash of the commit object (which includes the author, committer, date, message, and parent commit hashes) and the tree object. When someone else verifies the signature, their Git client uses your public key to decrypt the signature. If the decrypted signature matches a hash generated from the same commit object on their end, it confirms that the commit hasn’t been tampered with and that it was indeed signed by the holder of the corresponding private key. This process is what makes the signature "good."
Many developers overlook the importance of securing their GPG keys themselves. If your private GPG key is compromised, an attacker can impersonate you by signing commits with your identity. It’s crucial to protect your private key with a strong passphrase and to consider using hardware security modules (HSMs) or smart cards for storing your GPG private key for maximum security, especially if you are a high-profile contributor or handle sensitive code.
The next step is understanding how to integrate this with CI/CD pipelines for automated verification.