What Happens If a Commit Is Unsigned? (Forgejo Enforcement Across Machines)
In my previous post, I covered migrating from GPG to SSH commit signing.
If you have not read that first, start here:
This follow-up answers a practical question that appears as soon as you use multiple machines:
"If I commit from another machine and forget to sign, does push get rejected, or does it push and show untrusted?"
Short answer: it depends on enforcement.
Trust Labels vs Enforcement
These are separate controls and should not be confused:
- Trust model controls how Forgejo labels signed commits in the UI.
- Enforcement policy controls whether unsigned commits are allowed onto protected branches.
If you set:
FORGEJO__REPOSITORY_SIGNING__DEFAULT_TRUST_MODEL=committer
that affects trust evaluation and labels. It does not, by itself, block unsigned pushes.
What Happens When You Push an Unsigned Commit
Case 1: No signed-commit enforcement on the target branch
- Push succeeds.
- Commit is visible.
- Signature state is shown as unverified/untrusted (or not verified).
Case 2: Signed-commit enforcement enabled on the target branch
- Push is rejected.
- Your commit remains local.
- You re-sign locally, then push again.
Typical Multi-Machine Failure Mode
This usually happens because one machine is missing one of these:
gpg.format=sshcommit.gpgsign=trueuser.signingkey=<path-to-public-key>
It is rarely a Forgejo bug. It is usually configuration drift between environments.
Fast Recovery
Last commit only
git commit --amend --no-edit -S
git push --force-with-lease
Several recent commits
git rebase -i --exec "git commit --amend --no-edit -S" <base>
git push --force-with-lease
Use force-with-lease carefully and only on branches where rewrite is acceptable.
Practical Policy
For personal and small-team self-hosted workflows:
- Keep signing enabled globally on every machine.
- Use passphrase-protected private keys.
- Use
ssh-agentso passphrases are not a daily pain. - Enable signed-commit enforcement on protected branches where you want hard guarantees.
Forgejo Protected Branch Checklist
Use this as a quick hardening list for repositories where unsigned commits should never land on key branches.
- Protect your primary branch (for example
main). - Enable the signed-commit requirement in branch protection.
- Keep your trust model set to
committerat server level unless you have a specific reason not to. - Test from a machine with signing configured and confirm push succeeds.
- Test from a machine without signing configured and confirm push is rejected.
- Document the recovery command for contributors:
git commit --amend --no-edit -S
git push --force-with-lease
This gives you both visibility (trust labels) and enforcement (blocked unsigned pushes).
Appendix: Windows and WSL Parity Checklist
If you commit from both Windows and WSL, run this in each environment and compare outputs.
git --version
git config --show-origin --get gpg.format
git config --show-origin --get user.signingkey
git config --show-origin --get commit.gpgsign
git log --show-signature -1
Expected minimum parity:
gpg.format=sshcommit.gpgsign=true- A valid
user.signingkeypath for that environment
On Windows, also check which Git binaries are available:
where.exe git
If parity checks fail, treat it as configuration drift and fix before relying on enforcement.
Final Thought
Trust labels are a visibility tool. Enforcement is a control.
Use both deliberately: labels to understand provenance, enforcement to protect critical branches.
