通過 ssh, 在遠端要 sign commit 時, 會發生如下錯誤

error: gpg failed to sign the data
fatal: failed to write commit object

對 git trace 看看

$ GIT_TRACE=1 git commit -m "commit message..."
18:23:17.012581 git.c:415               trace: built-in: git commit -m 'remove auto generated files'
18:23:17.014894 run-command.c:643       trace: run_command: gpg --status-fd=2 -bsau B4712069D3F15B2A27910961E109CC97553EF
error: gpg failed to sign the data
fatal: failed to write commit object

試試 git 下的命令

$ gpg --status-fd=2 -bsau B4712069D3F15B2A27910961E109CC97553EF
[GNUPG:] KEY_CONSIDERED B4712069D3F15B2A27910961E109CC97553EF 2
[GNUPG:] BEGIN_SIGNING H8

再試試 sign 東西

$ echo test | gpg --status-fd=2 -bsau B4712069D3F15B2A27910961E109CC97553EF
[GNUPG:] KEY_CONSIDERED B4712069D3F15B2A27910961E109CC97553EF 2
[GNUPG:] BEGIN_SIGNING H8
[GNUPG:] PINENTRY_LAUNCHED 19547 curses 1.1.0 - screen-256color -
gpg: signing failed: Inappropriate ioctl for device
[GNUPG:] FAILURE sign 83918950
gpg: signing failed: Inappropriate ioctl for device

加個密要操作 device!? 什麼情況? 再找了找, 原來是 gnupg 會用 pinentry 在 console 詢問 private key 的密碼, 所以會需要操作 tty, 但... 搞錯對象了, 所以才會有 ioctl 的操作錯誤. 解法是設定環境變數, 例如

$ export GPG_TTY=$(tty); echo test | gpg --status-fd=2 -bsau B4712069D3F15B2A27910961E109CC97553EF

也可以設在你的 ~/.bashrc 中, 參考 Configure pinentry to use the correct TTY.

認證過了以後, 正常加密的輸出如下

$ echo test | gpg --status-fd=2 -bsau B4712069D3F15B2A27910961E109CC97553EF
[GNUPG:] KEY_CONSIDERED B4712069D3F15B2A27910961E109CC97553EF 2
[GNUPG:] BEGIN_SIGNING H8
[GNUPG:] SIG_CREATED D 17 8 00 1547635005 B4712069D3F15B2A27910961E109CC97553EF
-----BEGIN PGP SIGNATURE-----

iHUEABEIAB0WIQS0cSBp0/FbKieRCWHhCcyXVT7wCQUCXD8JPQAKCRDhCcyXVT7w
CTjFAP9SErgjg/3gnskOg23qCbSaPCwa1/j6rUEL3exaIYUFEQD/TfWm79n+u7Kd
4rt+kj5Eh94tnZ8OtAmMlkernUfzakg=
=Lv2i
-----END PGP SIGNATURE-----