Obsidian's comment is spot-on: the name of each Git object is the hash ID of the object's content, so anything that uses the ID to look up and read the content can, and usually does, verify that the hash of the extracted data matches the ID used as a key to extract that data.
Additional checking—verifying that the GPG signature in a tag or commit—is only done when you specifically request it. You can request that git log
check such signatures by default, using the log.showSignature
configuration setting.
Note that the integrity of any node in a Merkle tree depends on whether you trust prior nodes against second-preimage attacks. If you use GPG-signed tags, the signatures in those tags protect each tag's data (to whatever degree you trust GPG itself), and then the tag protects its commit object (to whatever degree you trust SHA-1). The commit object in turn protects its tree, which protects its subtrees and blobs, and the blob hashes protect their contents. So you should do a different kind of analysis if you're concerned with second-preimage attacks. If you're just concerned with random data corruption (as seen on spinning media and/or non-ECC memory), you can just use the SHA-1 hash directly the way Git does.