SHA-1 is the Secure Hash Algorithm 1, producing a 160-bit value written as 40 hex characters. In Git, every object (blob, tree, commit, tag) is addressed by its SHA-1.
How Git computes an object's SHA
Not from the raw content, but from a string with a prefix:
<type> <length-in-bytes>\0<content>
For a blob containing hello\n (6 bytes):
blob 6\0hello\n
Prefix plus content goes into SHA-1, producing 40 characters.
This means a blob and a tree with the same underlying bytes will have different SHAs, because the prefix differs.
The SHAttered attack (2017)
In February 2017, Google and CWI Amsterdam published two different PDF files with the same SHA-1. The effort was roughly 6,500 CPU-years and cost around $100k at the time. It was the first practical demonstration of a SHA-1 collision.
From a cryptographic standpoint, SHA-1 is broken for signatures and identity after that. For Git, the impact is less severe than it appears:
- SHA-1 in Git is an address, not a signature.
- The
<type> <length>\0prefix makes an attack harder: a collision must match not just arbitrary bytes but bytes with a known prefix and fixed length. - Since 2017, Git checks every incoming object for signs of a SHAttered attack and refuses to accept known-colliding objects.
Migration to SHA-256 has been underway since 2018.
SHA-256 in Git
Since Git 2.29 (2020), you can create a repository with a different hash algorithm:
git init --object-format=sha256
SHA-256 produces 64-character hashes instead of 40. There is no compatibility with SHA-1 repositories: a repository uses one or the other. Most public hosting services (GitHub, GitLab) do not yet support SHA-256, so all live projects are effectively on SHA-1.
Short SHAs
You can pass just the first 4 or more characters to Git commands:
git show 8d0e41 # instead of 8d0e41234f24...
If several objects share that prefix, Git reports an "ambiguous" error and
you need more characters. By default Git picks the shortest prefix that
is unambiguous (at least 7 characters with --abbrev).
Pitfalls
- SHA-1 creates a false sense of authenticity. For cryptographic
guarantees, sign your commits with GPG or SSH (
git commit -S). The SHA alone does not protect against forgery. - SHA-1 in Git is not an HMAC and does not involve a secret. Anyone can compute the SHA of any content.
- In scripts, do not parse short SHAs. Use
git rev-parse --abbrev-commit <ref>or work with the full form.