How Git Uses SHA-1 and SHA-256 for Object IDs

How Git computes object IDs for blobs, trees, commits, and tags using SHA-1 and SHA-256. The header format, transition plan, and collision risk in practice.

ZERO UPLOAD · ALL LOCAL
  1. Type or paste any string into the input box — all four hashes update instantly as you type.
  2. Use the HEX / BASE64 toggle above the results to switch output format at any time.
  3. Click Copy next to any hash to copy it to the clipboard in the current format.
  4. Switch to HMAC, enter your secret key, and pick an algorithm to generate a keyed digest for API signatures or webhook verification.
  5. SHA-256 is the recommended algorithm for new integrations. MD5 and SHA-1 are shown for legacy compatibility only.

Worked examples for this use case

Computing a blob OID manually

Before
File content: "Hello, World!" (13 bytes)
Git header format: "blob 13\0"
After
Concatenate: "blob 13\0Hello, World!"
SHA-1 of concatenated bytes = Git blob OID
Verify: git hash-object path/to/file

The SHA-1 python example in this tool shows the exact hashlib pattern for replicating Git's header-prefixed hashing.

Comparing SHA-1 and SHA-256 repository OID lengths

Before
SHA-1 commit OID: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2 (40 hex chars)
After
SHA-256 commit OID: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 (64 hex chars)

Create a SHA-256 repository with: git init -object-format=sha256

MD5 LEGACY
SHA-1 LEGACY
SHA-256 RECOMMENDED
SHA-512 SECURE
SHA-256

How Git Uses SHA-1 and SHA-256 for Object IDs

Git stores files, trees, commits, and tags as content-addressable objects. Every object stored by Git - a file, a directory tree, a commit, a tag - receives an object ID (OID) derived from a SHA hash of its content.1 Because two objects with different content have (with overwhelming probability) different hashes, Git uses the OID as both an identifier and an integrity check: if the stored bytes produce the expected OID, the object is intact.

Git has used SHA-1 since its creation in 2005. Following the SHAttered collision demonstration in 2017, Git began transitioning to SHA-256 through its object-format feature introduced in Git 2.29.23 SHA-256 repositories are now production-stable but not yet the default. Most repositories in the world still use SHA-1 OIDs, including the Linux kernel and every major open-source project.

How Git computes an object ID

Git does not hash a file's bytes directly. Instead, it prepends a header before hashing. For a blob (file content), the header is the string "blob", a space, the content length in decimal, and a null byte: "blob 13\0Hello, World!". For a commit, the header is "commit \0". This prefix prevents accidental collisions between objects of different types that happen to have the same content. Consequently, you can reproduce any Git OID outside of Git by constructing the same header and hashing with SHA-1 or SHA-256.

Separating object type from content length

The header type and length are part of the object identity, not documentation. A blob containing the bytes "13" and a commit object containing different metadata cannot collide merely because their raw content overlaps, because Git hashes the type-prefixed byte sequence. When reproducing OIDs manually, preserve the exact ASCII header, the decimal byte count, and the null byte separator. This design choice means that even if two objects of different types happen to share identical content bytes, their OIDs will always differ because the type prefix and length field make the hashed input unique to each object category.

You reproduce a correct OID only when you preserve the exact ASCII header, the decimal byte count, and the null byte separator that Git prepends before hashing. Omitting the null byte produces a hash that resembles a blob OID but matches no real object in the repository. CapyToolkit can reproduce the header-prefixed SHA-1 blob OID locally, so you can verify Git-style hashing without uploading file contents.

The SHA-1 collision risk in Git

The SHAttered attack demonstrated that two files with the same SHA-1 exist, but exploiting this in a Git repository requires crafting a commit whose OID collides with a legitimate one - a significantly harder problem than a general-purpose collision. Furthermore, Git 2.23+ includes protections that detect known SHA-1 collision patterns in blobs. Building on this defense: the practical attack vector is narrow; a collision would let an attacker substitute one blob for another in a repository they already control. The risk is low for open-source projects where content is reviewed, but nonzero for supply chain attacks against automated CI pipelines.

Treating collision risk as a trust-boundary question

A casual checksum collision and an attacker-controlled Git object collision are not the same scenario. Git's content-addressed model still catches accidental corruption, but systems that accept untrusted commits or generated blobs should prefer SHA-256 repositories where the hosting platform and CI tooling support them. The key question is whether the people submitting content to your repository are trusted contributors or arbitrary external parties, because a collision attack requires the attacker to control the exact bytes that get hashed, which is only possible when the attacker can influence what enters the object store in the first place.

The SHA-256 transition

Create a SHA-256 repository with git init -object-format=sha256. Object IDs in SHA-256 repositories are 64 hex characters rather than 40.4 Existing SHA-1 repositories cannot be converted in place - the transition plan requires translating all OIDs, which Git does not yet automate for production use. Git 2.42+ introduced interoperability improvements, but most hosting platforms and tools still treat SHA-1 as the default. Yet the migration is underway: GitHub and GitLab have both published support timelines. New repositories that expect to exist for decades are reasonable candidates for SHA-256 from the start.

Checking tool support before choosing SHA-256

Before initializing a SHA-256 repository, verify that your CI runners, IDE plugins, mirror infrastructure, and backup tooling understand the new OID length. A repository that works locally can still fail in automation if one tool truncates OIDs or assumes 40 hex characters. SHA-256 is strongest when the whole toolchain agrees on it. Start by testing your most constrained environment first, which is often the CI runner or the oldest IDE version your team still supports, because those are the places where silent truncation or hardcoded OID-length assumptions are most likely to hide.

Reproducing a Git blob OID from file content outside of Git

Feeding a file's raw content through the same header construction confirms your implementation gets the format right, and it lets you reproduce a blob OID without a local repo to test against. Construct the header by concatenating these bytes in order: the ASCII string "blob", a single space character, the byte length of the file content formatted as decimal ASCII, and a null byte (0x00). Append the raw file content bytes immediately after. Compute SHA-1 over the full byte sequence.5 The result matches git hash-object exactly for any standard SHA-1 repository.

This pattern is useful when building custom Git tooling, verifying a content-addressable storage implementation, or debugging a discrepancy between a working tree file and its OID in the Git index. The null byte separator is the most commonly missed element; omitting it produces a hash that resembles a blob OID but matches no real object in the repository.

When to use this

Use the Hash Generator to reproduce a Git blob OID when debugging a repository integrity issue, building a custom Git object store, or verifying that a file matches a specific commit's version without checking out the repository.

Examples

Computing a blob OID manually

Before
File content: "Hello, World!" (13 bytes)
Git header format: "blob 13\0"
After
Concatenate: "blob 13\0Hello, World!"
SHA-1 of concatenated bytes = Git blob OID
Verify: git hash-object path/to/file

The SHA-1 python example in this tool shows the exact hashlib pattern for replicating Git's header-prefixed hashing.

Comparing SHA-1 and SHA-256 repository OID lengths

Before
SHA-1 commit OID: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2 (40 hex chars)
After
SHA-256 commit OID: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 (64 hex chars)

Create a SHA-256 repository with: git init -object-format=sha256

Sources
  1. 1.

    Git, "Git Internals – Git Objects," git-scm.com, accessed June 2026. https://git-scm.com/book/en/v2/Git-Internals-Git-Objects

  2. 2.

    Google Security Blog, "Announcing the first SHA1 collision," googleblog.com, February 23, 2017. https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html

  3. 3.

    Git, "git-init — 2.29.0," git-scm.com, accessed June 2026. https://git-scm.com/docs/git-init/2.29.0

  4. 4.

    "SHA-2," Wikipedia, accessed June 2026. https://en.wikipedia.org/wiki/SHA-2

  5. 5.

    Git, "object-file.c — format_object_header," github.com/git/git, accessed June 2026. https://github.com/git/git/blob/master/object-file.c

FAQ