gitsign

Can I sign a git tag after it was created?


I created a tag and forgot to sign it, then pushed the tag to GitHub. Is it possible to just sign that tag retroactively, or do I have to create a new tag?

I have read the man page for git tag and googled a bit, but have come up with no clues that adding a signature to an already existing tag is possible.


Solution

  • No you would need to::

    As mrts adds in the comments, since the tag was already pushed:

    You also need to force push the updated tag with git push origin <tag_name> -f


    Starting with Git 2.42 (Q3 2023), you can sign only the tags which need it, using:

    git for-each-ref --format='%(refname) %(signature)' refs/tags | python re-sign-tags.py
                                          ^^^^^^^^^^^^
                                       (new with Git 2.42)
    

    And re-sign-tags.py

    import sys
    import subprocess
    
    def verify_tag(refname, signature):
        grade = signature.split(":")[1]
        if grade == "good":
            print("Tag '%s' is signed with a good signature." % refname)
        else:
            print("Tag '%s' is signed with a bad signature." % refname)
    
    def re_sign_tag(refname, signature):
        signer = signature.split(":")[1]
        print("Re-signing tag '%s' with key '%s'." % (refname, signer))
        subprocess.run(["git", "tag", "-f", refname, refname, "-s"], check=True)
    
    if __name__ == "__main__":
        for refname, signature in sys.stdin:
            if refname.startswith("refs/tags/"):
                if verify_tag(refname, signature):
                    re_sign_tag(refname, signature)
    

    With Git 2.42 (Q3 2023), the "git for-each-ref"(man) family of commands learned placeholders related to GPG signature verification.

    See commit 26c9c03, commit 2f36339 (04 Jun 2023) by Kousik Sanagavarapu (five-sh).
    (Merged by Junio C Hamano -- gitster -- in commit 81ebc54, 14 Jul 2023)

    ref-filter: add new "signature" atom

    Co-authored-by: Hariom Verma
    Co-authored-by: Jaydeep Das
    Co-authored-by: Nsengiyumva Wilberforce
    Mentored-by: Christian Couder
    Mentored-by: Hariom Verma
    Signed-off-by: Kousik Sanagavarapu

    Duplicate the code for outputting the signature and its other parameters for commits and tags in ref-filter from pretty.
    In the future, this will help in getting rid of the current duplicate implementations of such logic everywhere, when ref-filter can do everything that pretty is doing.

    The new atom "signature" and its friends are equivalent to the existing pretty formats as follows:

    %(signature) = %GG
    %(signature:grade) = %G?
    %(siganture:signer) = %GS
    %(signature:key) = %GK
    %(signature:fingerprint) = %GF
    %(signature:primarykeyfingerprint) = %GP
    %(signature:trustlevel) = %GT
    

    git for-each-ref now includes in its man page:

    signature

    The GPG signature of a commit.

    signature:grade

    Show "G" for a good (valid) signature, "B" for a bad signature, "U" for a good signature with unknown validity, "X" for a good signature that has expired, "Y" for a good signature made by an expired key, "R" for a good signature made by a revoked key, "E" if the signature cannot be checked (e.g. missing key) and "N" for no signature.

    signature:signer

    The signer of the GPG signature of a commit.

    signature:key

    The key of the GPG signature of a commit.

    signature:fingerprint

    The fingerprint of the GPG signature of a commit.

    signature:primarykeyfingerprint

    The primary key fingerprint of the GPG signature of a commit.

    signature:trustlevel

    The trust level of the GPG signature of a commit. Possible outputs are ultimate, fully, marginal, never and undefined.