Signing Git Commits and Tags Without Breaking Your Release Pipeline

May 23, 2026 3 min read 35 views
minimalist

Anyone can set user.name and user.email in Git to whatever they like and push commits that look like they came from you. Without signing, there is no cryptographic proof that a commit or tag was actually authored by the person whose name is on it. That gap matters a lot when you are cutting a release that downstream users or package managers are going to trust.

Setting up signing sounds simple until your CI runner fails with a cryptic GPG error at 2 AM, or your automated release tool stops being able to create signed tags. This guide walks you through signing commits and tags correctly β€” and keeping your pipeline healthy throughout.

What you'll learn

  • How GPG and SSH signing work in Git and when to use each.
  • How to configure signing for local development without friction.
  • How to sign commits and tags in CI/CD runners.
  • How to enforce signature verification as a policy without locking out your own automation.
  • Common mistakes that silently break pipelines and how to avoid them.

Prerequisites

You should be comfortable with basic Git workflows β€” commits, tags, remotes. The examples use git version 2.34 or later (when SSH signing was introduced), gpg version 2.x, and a Linux or macOS environment. Windows users can follow along using Git for Windows or WSL, though some paths differ.

GPG vs SSH Signing: Which One to Use

Git supports two signing backends: GPG (the classic option) and SSH keys (added in Git 2.34). Both produce a cryptographic signature; the difference is in key management and tooling overhead.

GPG gives you a full public-key infrastructure: key expiry, subkeys, revocation certificates, and integration with the Web of Trust. It is the standard for signing official open source releases because the ecosystem around it is mature. The downside is that GPG key management has a steep learning curve and the agent behavior is notoriously fiddly.

SSH signing reuses the SSH key you almost certainly already have. If you use GitHub or GitLab with SSH authentication, you can sign commits with the exact same key. It is simpler to set up and reason about. The trade-off is that SSH signing has less tooling support for revocation and expiry, and older Git hosts may not verify SSH-signed objects yet.

For personal projects or team-internal repos, SSH signing is the pragmatic choice. For public open source packages where you want a trust chain that others can audit, GPG is worth the extra setup.

Setting Up GPG Signing Locally

Start by listing your existing secret keys to see if you already have one worth using.

gpg --list-secret-keys --keyid-format=long

If the list is empty, generate a new key. Prefer Ed25519 for smaller keys and faster operations.

gpg --full-generate-key
# Choose: ECC (sign only) β†’ Curve 25519 β†’ 2y expiry β†’ your real name and email

Once the key exists, grab its long ID from the listing output. It looks like 3AA5C34371567BD2. Tell Git to use it globally.

git config --global user.signingkey 3AA5C34371567BD2
git config --global commit.gpgsign true
git config --global tag.gpgsign true

Setting commit.gpgsign and tag.gpgsign to true means every commit and tag you create will be signed automatically. You do not need to pass -S manually each time.

Pointing Git at the right GPG binary

On macOS with Homebrew, the GPG binary might be gpg2 rather than gpg. If Git cannot find it, set the path explicitly.

git config --global gpg.program gpg2

Also make sure the GPG agent is running and has your passphrase cached, otherwise every commit will block waiting for a PIN entry dialog. Add this to your shell profile to start the agent on login.

export GPG_TTY=$(tty)

Setting Up SSH Signing Locally

If you prefer SSH, the setup is shorter. First tell Git which key to use and which backend to use.

git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
git config --global tag.gpgsign true

Note that user.signingkey points to the public key file path, not the private key. Git resolves the corresponding private key through your SSH agent. Run ssh-add ~/.ssh/id_ed25519 if the agent does not already have it loaded.

Setting up the allowed signers file

To verify SSH-signed commits, Git needs a file that maps email addresses to public keys. Create one at ~/.ssh/allowed_signers.

you@example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...

Then point Git at it.

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

Without this file, git verify-commit will always report the signer as unknown even if the signature itself is cryptographically valid.

Uploading Your Public Key to the Git Host

Signing is only half the picture. Your Git host (GitHub, GitLab, Gitea) needs your public key to show a

Tags: #Verified

πŸ“€ Share this article

Sign in to save

Comments (0)

No comments yet. Be the first!

Leave a Comment

Sign in to comment with your profile.

πŸ“¬ Weekly Newsletter

Stay ahead of the curve

Get the best programming tutorials, data analytics tips, and tool reviews delivered to your inbox every week.

No spam. Unsubscribe anytime.