38

Is there a way to sign git commits with gpg? It's so easy with tags (using -s instead of -a), it seems there would be a similar function for commits.

Eugene
  • 10,957
  • 20
  • 69
  • 97
austin1howard
  • 4,815
  • 3
  • 20
  • 23
  • 2
    Why do you want to sign every commit? If you sign a tag, all commits reachable from that tag are also signed (due to the parent ids being included in each commit's hash). There's little benefit in signing each and every commit. – knittl Apr 09 '12 at 18:42
  • Interesting...so if I were to tag and sign my initial commit, all subsequent commits from me would be signed? How would I verify the signatures? – austin1howard Apr 09 '12 at 19:00
  • 1
    @Magnesium no, the commits won't be signed but they still can be trusted because you can't change them without breaking the tag signature. – wRAR Apr 09 '12 at 19:10
  • 5
    @Magnesium: no. There are no commits reachable from the initial commit. It only works the other way round. If you sign your latest commit (have a signed tag point to it) all commits before that (parents/ancestors) are automatically trusted. – knittl Apr 09 '12 at 19:25
  • 3
    one reason to sign each commit is to have stronger evidence that the commit actually came from the person you think it did. Signing tags only allows you to detect whether the history has changed. – Hans-Christoph Steiner Aug 02 '12 at 17:42
  • relevant: http://git.661346.n2.nabble.com/GPG-signing-for-git-commit-tp2582986p2583316.html – unhammer Jan 20 '13 at 13:26
  • 4
    The problem I see with only signing tags, is that for people who aren't linux kernel developers, it will be incredibly simple for somebody to push out commits that use your name and e-mail, and those being indistinguishable from the ones you did yourself. With social coding sites like github, where you contribute to many different projects, this could have serious impact on your reputation, if suddenly bad/malicious code pops up with your name on it, and with no way to tell it from the things you actually did. =) – cib May 21 '13 at 01:39
  • "and those being indistinguishable" -- not bloody likely. Every key has a fingerprint. Two keys with a shared claimed identity but different fingerprints, neither signed by the other, is a huge red flag even if you have no certification standards at all. Certification of a key's identity is as simple as checking whether someone you trust has signed off on the association. The kernel guys do it in-person, leaving what web browsers are pleased to call "certificates" on corporate identity looking like a dubious-looking note Mom supposedly wrote to excuse absence by comparison. – jthill Nov 22 '13 at 15:27
  • Possible duplicated: https://stackoverflow.com/questions/10161198/is-there-a-way-to-autosign-commits-in-git-with-a-gpg-key/ – Felipe Apr 06 '20 at 17:06
  • Does this answer your question? [Is there a way to gpg sign all previous commits?](https://stackoverflow.com/questions/41882919/is-there-a-way-to-gpg-sign-all-previous-commits) – Michael Freidgeim Aug 22 '23 at 12:47
  • 2
    @MichaelFreidgeim That asks a different question: if it is possible to sign **previous** commits. This questions asks how to sign commits, when you commit them. – Mark Rotteveel Aug 22 '23 at 17:04

2 Answers2

63

Note: Adding the -S option all the time can be cumbersome.
In git 2.0 and later, you can add a config which will take care of that option for you.

See commit 2af2ef3 by Nicolas Vigier (boklm):

Add the commit.gpgsign option to sign all commits

If you want to GPG sign all your commits, you have to add the -S option all the time.
The commit.gpgsign config option allows to sign all commits automatically.

commit.gpgsign

A boolean to specify whether all commits should be GPG signed.
Use of this option when doing operations such as rebase can result in a large number of commits being signed. It may be convenient to use an agent to avoid typing your GPG passphrase several times.

As Apteryx commented below:

To set this globally on the command line:

git config --global commit.gpgsign true

With Git 2.27 (Q2 2020), "git rebase" learned the "--no-gpg-sign" option to countermand commit.gpgSign the user may have.

See commit 5c5bac1, commit 4369d3a, commit 9da37fe, commit ae06ba6, commit cf0ad4d, commit c241371 (03 Apr 2020) by Đoàn Trần Công Danh (``).
(Merged by Junio C Hamano -- gitster -- in commit fc3f6fd, 22 Apr 2020)

cherry-pick/revert: honour --no-gpg-sign in all case

Signed-off-by: Đoàn Trần Công Danh

{cherry-pick,revert} --edit hasn't honoured --no-gpg-sign yet.

Pass this option down to git commit to honor it.


Note that "git rebase --rebase-merges"(man) did not correctly pass --gpg-sign command line option to underlying "git merge" when replaying a merge using non-default merge strategy or when replaying an octopus merge (because replaying a two-head merge with the default strategy was done in a separate codepath, the problem did not trigger for most users), which has been corrected with Git 2.30 (Q1 2021)

See commit 43ad4f2, commit 19dad04, commit ae03c97 (18 Oct 2020) by Samuel Čavoj (sammko).
(Merged by Junio C Hamano -- gitster -- in commit 73af6a4, 02 Nov 2020)

sequencer: fix gpg option passed to merge subcommand

Signed-off-by: Samuel Čavoj

When performing a rebase with --rebase-merges using either a custom strategy specified with -s or an octopus merge, and at the same time having gpgsign enabled (either rebase -S or config commit.gpgsign), the operation would fail on making the merge commit.

Instead of "-S%s" with the key id substituted, only the bare key id would get passed to the underlying merge command, which tried to interpret it as a ref.

Fix the issue and add test cases as suggested by Johannes Schindelin and Junio C Hamano.

And:

sequencer: pass explicit --no-gpg-sign to merge

Signed-off-by: Samuel Čavoj

The merge subcommand launched for merges with non-default strategy would use its own default behaviour to decide how to sign commits, regardless of what opts->gpg_sign was set to.
For example the --no-gpg-sign flag given to rebase explicitly would get ignored, if commit.gpgsign was set to true.

Fix the issue and add a test case exercising this behaviour.

Fixed in:

"git rebase --rebase-merges"(man) did not correctly pass --gpg-sign command line option to underlying "git merge" when replaying a merge using non-default merge strategy or when replaying an octopus merge (because replaying a two-head merge with the default strategy was done in a separate codepath, the problem did not trigger for most users), which has been corrected with Git 2.30 (Q1 2021), .

See commit 43ad4f2, commit 19dad04, commit ae03c97 (18 Oct 2020) by Samuel Čavoj (sammko).
(Merged by Junio C Hamano -- gitster -- in commit 73af6a4, 02 Nov 2020)

sequencer: fix gpg option passed to merge subcommand

Signed-off-by: Samuel Čavoj

When performing a rebase with --rebase-merges using either a custom strategy specified with -s or an octopus merge, and at the same time having gpgsign enabled (either rebase -S or config commit.gpgsign), the operation would fail on making the merge commit.
Instead of "-S%s" with the key id substituted, only the bare key id would get passed to the underlying merge command, which tried to interpret it as a ref.

Fix the issue and add test cases as suggested by Johannes Schindelin and Junio C Hamano.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 3
    To set this globally on the command line: `git config --global commit.gpgSign true` – Apteryx May 30 '16 at 06:18
  • @Apteryx Thank you. I have included your comment in the answer for more visibility. – VonC May 30 '16 at 06:21
  • Strange question, but is there a similar flag to temporarily suspend the ```config.gpgsign=true``` other than doing a separate ```git config --global commit.gpgsign false``` followed by a subsequent ```git config --global commit.gpgsign true```? – Chris.Wilson Nov 22 '16 at 17:36
  • 3
    @Chris.Wilson you can suspend it at the repo level (`cd /path/to/repo; git config commit.gpgsign false`). Or you can suspend it at the command level: `git -c commit.gpgsign=false xxx`. Both would take precedence over the global config. – VonC Nov 22 '16 at 18:28
36

git commit -S (requires git >= 1.7.9).

wRAR
  • 25,009
  • 4
  • 84
  • 97
  • 8
    Or equivalently `gpg commit --gpg-sign`. You can also use `gpg commit --gpg-sign=DEADBEEF` to specify a key. I found this out by looking at the source code; it doesn't seem to be documented. – Keith Thompson Apr 09 '12 at 19:00
  • 1
    It's documented in --help and relnotes, but not in the manpage. – wRAR Apr 09 '12 at 19:09
  • 2
    Well that would explain why i don't see it, I'm on 1.7.8 for backwards compatibility. I guess they read my mind! – austin1howard Apr 09 '12 at 19:10
  • @wRAR: `gpg commit --help` just shows the man page, and I don't see it anywhere in the relnotes. I'm looking at the current sources from git://github.com/gitster/git.git. Can you post the exact command you use to display documentation that mentions `-S`, or the name of a file or URL of a web page? Thanks. – Keith Thompson Apr 09 '12 at 20:45
  • @KeithThompson right, I tried `-h` which is not an alias for `--help` so it displays usage info. Relnotes are `Documentation/RelNotes/1.7.9.txt` – wRAR Apr 10 '12 at 08:36
  • @wRAR: I missed the reference in the RelNotes because I was searching for `gpg-sign`; `--gpg-sign` is the long form of `-S`. 1.7.9.txt says: *"git commit" learned "-S" to GPG-sign the commit; this can be shown with the "--show-signature" option to "git log".* – Keith Thompson Apr 10 '12 at 09:11
  • 1
    Git will use the key in the git-config variable `user.signingkey` – u0b34a0f6ae Mar 03 '13 at 08:42
  • 7
    Is there a way to make --gpg-sign the default for `git commit`? – Hongli Mar 10 '13 at 23:02
  • @Hongli you can always make an alias – wRAR Mar 10 '13 at 23:16
  • 2
    @wRAR unfortunately, that only works for commits that the user explicitly creates using `git commit`. If you do a rebase, for instance, and want to sign all the new commits it makes, an alias won't let you do that. The only way I'm aware of is to do an interactive rebase and manually sign each commit. It's similar with non-fast-forward merges, where the merge commit won't be signed unless if you do a `git merge --no-commit ...`. – Patrick Niedzielski Dec 06 '13 at 22:05
  • 3
    "git commit" can be told to always GPG sign the resulting commit by setting the commit.gpgsign configuration variable to true (no-gpg-sign should override the command-line option). http://sdt.bz/68912#ixzz2vqXtbO71 – rofrol Mar 13 '14 at 12:48