First, identify which key you want to back up:
$ gpg --list-secret-keys --keyid-format=long
Find your key ID — it appears after rsa4096/ (or ed25519/) on the sec line:
sec rsa4096/ABCDEF1234567890 2026-03-13 [SC] [expires: 2027-03-13]
C1CB417F5F2F9E4D147F01C4ABCDEF1234567890
uid [ultimate] John Doe <john.doe@datawords.asia>
ssb rsa4096/1234567890ABCDEF 2026-03-13 [E] [expires: 2027-03-13]
Export your private key (this is the critical part — without it you cannot sign commits):
$ gpg --armor --export-secret-keys ABCDEF1234567890 > gpg-private-key.asc
Also export your public key:
$ gpg --armor --export ABCDEF1234567890 > gpg-public-key.asc
Export the trust database so your key trust level is preserved:
$ gpg --export-ownertrust > gpg-ownertrust.txt
gpg-private-key.asc) gives full access to your GPG identity. Treat it like a password — never send it over email or messaging apps in plain text.
$ gpg --show-keys gpg-private-key.asc
$ gpg --show-keys gpg-public-key.asc
Move the exported files to your new machine securely. Here are recommended methods:
Option 1: USB drive (recommended)
# Copy to USB
$ cp gpg-private-key.asc gpg-public-key.asc gpg-ownertrust.txt /media/usb/
# After copying to new machine, securely delete from USB
$ shred -u /media/usb/gpg-private-key.asc
Option 2: SCP (over SSH)
$ scp gpg-private-key.asc gpg-public-key.asc gpg-ownertrust.txt user@newmachine:~/
$ shred -u gpg-private-key.asc gpg-public-key.asc gpg-ownertrust.txt
shred -u overwrites the file content before deleting. On macOS, use rm -P instead. On Windows, simply delete the files — shred is not available.
On the new machine, import the keys and trust database:
Import the private key (this also imports the public key):
$ gpg --import gpg-private-key.asc
[pinentry dialog will appear — enter your passphrase]
gpg: key ABCDEF1234567890: secret key imported
gpg: Total number processed: 1
gpg: imported: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
Import the public key (in case it was not included with the private key export):
$ gpg --import gpg-public-key.asc
Restore the trust database:
$ gpg --import-ownertrust gpg-ownertrust.txt
If you did not back up the trust database, set the trust level manually:
$ gpg --edit-key ABCDEF1234567890
gpg> trust
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu
Your decision? 5
gpg> quit
Re-configure Git to use the key for commit signing:
$ gpg --list-secret-keys --keyid-format=long
# Find your key ID from the output
$ git config --global user.signingkey ABCDEF1234567890
$ git config --global commit.gpgsign true
$ shred -u gpg-private-key.asc gpg-public-key.asc gpg-ownertrust.txt
Confirm the key was imported correctly:
$ gpg --list-secret-keys --keyid-format=long
sec rsa4096/ABCDEF1234567890 2026-03-13 [SC] [expires: 2027-03-13]
C1CB417F5F2F9E4D147F01C4ABCDEF1234567890
uid [ultimate] John Doe <john.doe@datawords.asia>
ssb rsa4096/1234567890ABCDEF 2026-03-13 [E] [expires: 2027-03-13]
Make sure the trust level shows [ultimate]. If it shows [unknown], go back and set the trust level.
Create a test commit to verify signing works:
$ cd /path/to/any/repo
$ git commit --allow-empty -m "test: verify GPG signing on new machine"
Check that the commit is signed:
$ git log --show-signature -1
commit abc123...
gpg: Signature made ...
gpg: Good signature from "John Doe <john.doe@datawords.asia>"
...
Push to Gitea and check that the commit shows the green "Verified" badge.
| Problem | Solution |
|---|---|
gpg: decryption failed: No secret key |
The private key was not imported. Run gpg --import gpg-private-key.asc again and make sure no errors appear. |
Trust level shows [unknown] instead of [ultimate] |
Run gpg --edit-key KEY_ID, then trust, select 5 (ultimate), and quit. |
gpg: signing failed: No secret key when committing |
Check that git config user.signingkey matches your key ID. Run gpg --list-secret-keys --keyid-format=long to confirm. |
error: gpg failed to sign the data |
Run export GPG_TTY=$(tty) and retry. Add this to your shell profile (~/.bashrc or ~/.zshrc). |
| Key shows as expired after import | Extend the expiration: gpg --edit-key KEY_ID → expire → set new date → save. Then re-export the public key and update it on Gitea. |
| Passphrase dialog does not appear | Install pinentry for your platform: brew install pinentry-mac (macOS), sudo apt install pinentry-curses (Linux). Then restart gpg-agent: gpgconf --kill gpg-agent. |