Scott Chacon, who co-founded GitHub, says Git 3.0's plan to make SHA-256 the default hash for new repositories is a mistake, and his September 30 post on the GitButler blog spent October 2 near the top of Hacker News. The Git project's own position is that SHA-1 was deprecated by NIST in 2011 and the default has to move while there is still time. Both sides are working from the same facts. They disagree about who pays.

I run a lot of Git. Mirrors, hooks, CI runners, backup jobs that walk repositories, and tooling that has assumed a commit ID is 40 hex characters since before some of my coworkers could drive. So I read Chacon's argument as an operator, and I think he's about 70 percent right.

What Git 3.0 changes, and when

The change is narrow on paper. Git's breaking changes document says new repositories created with git init will use the sha256 object format instead of sha1. Existing repositories keep their format. There is no plan to deprecate sha1. The document lists four published attacks (SHAppening in 2015, SHAttered in 2017, a 2019 chosen-prefix attack at 2^68 operations, and Shambles in 2020 at 2^63) and says the project expects more. It also sets one condition: the libraries, applications and forges around Git have to be ready first.

The timeline firmed up last month. According to LWN's coverage of Git 2.56, the December 2026 release will be numbered 2.98, a 2.99 LTS release follows in April 2027, and Git 3.0 ships alongside it. So the default flips in about six months, assuming that readiness condition is met. Git 3.0 also requires a working Rust compiler and makes reftable the default ref storage. The hash change is the one that reaches past the Git binary into everything that touches a commit ID.

SHA-256 support itself is old news. It landed in Git 2.29 in October 2020 and stopped being labeled experimental in 2.42 in 2023. You can create a SHA-256 repository today with git init --object-format=sha256. The IDs come out at 64 characters. Nothing else in your stack knows what to do with them.

Chacon's case

His argument has three parts. First, no SHA-1 collision has ever been found inside a Git repository, across billions of objects, and the known attacks cost tens of thousands of dollars in GPU time to produce one pair of colliding files. Git has shipped SHA-1DC, the variant of the hash that detects collision attempts, since 2.13 in 2017, so an object built with the SHAttered technique gets rejected at the door anyway.

Second, hashes were never the trust mechanism. He quotes Linus Torvalds from 2005: "The real security is in distribution." You trust a commit because of where you pulled it from and who signed it, and an attacker with a maintainer's credentials doesn't need a collision. The xz backdoor in 2024 needed zero cryptanalysis.

Third, the costs of running two formats are concrete and land on everyone. Submodules only work when parent and child share a hash format. Every tool with a 40-character regex breaks. Every commit link in an old issue tracker, Slack thread or email stops resolving if a project ever converts. Libraries that reimplement Git without linking to it (and there are many) mostly have no SHA-256 support at all. And today, pushing a SHA-256 repository to GitHub fails with "the receiving end does not support this repository's hash algorithm." Chacon also reports that Google, per a talk by Emily Shaffer, may set an override at the system level to keep new internal repositories on SHA-1.

His alternative is to leave the object format alone and add an independent SHA-256 hash of the full tree contents as a header inside signed commits and tags. Verification would be optional. His prototype hashes the 35 GB, 2.1 million file Chromium tree in 5 seconds, the Linux tree in 257 milliseconds, and Git's own tree in 17 milliseconds. Projects that need to satisfy NIST's rule that SHA-1 not be used for cryptographic protection after 2030 would have a signed SHA-256 digest to point at, and nobody else would have to change anything.

Where he's right, and where the Git project is

He's right that the attack scenario is thin. A chosen-prefix collision against a Git object has to survive SHA-1DC, has to produce a valid object of the right type, and has to get past code review and into a repository people pull from. If you can do that last part, you already own the project.

He's also right about the bill. I've watched what happens when an identifier changes width. The SHA-1 assumption is baked into shell scripts, database columns, log parsers, deploy tooling and monitoring dashboards that nobody has looked at in years. Those don't break on upgrade day. They break the first time someone on a new laptop runs git init without thinking and pushes the result into a pipeline.

But the Git maintainers aren't claiming the attack is practical today. They're claiming that SHA-1 attacks only get cheaper and that a default is the only lever they have to make a migration start. They've been working on this since 2017. The SHA-256 format has been out of experimental status for three years. If the default never moves, the tools around Git never finish the work, and the project gets stuck defending a hash that NIST disallows for every purpose after December 31, 2030. Compliance teams will not care that the trust was in distribution all along.

The gap between the two positions is the interoperability layer, and that's the part that doesn't exist yet. Git's documentation describes translation tables that would let a SHA-256 repository talk to SHA-1 peers through a compatibility object format. Multiple people in the Lobsters thread reported that turning it on fails with a "requires Rust" error on stock builds of macOS, Fedora and Ubuntu. GitLab has supported SHA-256 repositories since 2024. Forgejo supports them. GitHub has a private preview, and brian m. carlson, who leads the transition and works at GitHub, told the mailing list that news was coming. That is the single biggest blocker, and it's been the biggest blocker for five years.

Flip the default before GitHub ships and before the translation layer works on a default build, and the first six months of Git 3.0 are a support ticket generator. Flip it after both exist, and the cost drops to a regex audit.

What to do this quarter

You don't need to pick a side to prepare. Four things to do before April:

  1. Grep your automation for [0-9a-f]{40}, substr(0, 40), and CHAR(40) column definitions. Make them accept 64 as well. This is cheap now and expensive in a 3 a.m. incident.
  2. Decide on a policy and enforce it with config, not memory. If your shop can't absorb SHA-256 repositories yet, set init.defaultObjectFormat=sha1 in the system or global config on developer machines and CI images. That's what Google is apparently planning, and it's the correct move for any team with submodules or homegrown Git tooling.
  3. Create one SHA-256 repository on purpose and run your real pipeline against it. Hooks, signing, mirrors, backup. Find out what breaks while nothing is on fire.
  4. Check whether your forge supports it. GitLab and Forgejo do. If you run something else yourself, open the issue now.

Borg Backup Server doesn't care what Git hashes with, since it chunks files and not objects. But the scripts around it that pull from Git and tag releases do, and I have the same 40-character assumptions in them as everyone else. I'll be doing the audit above this month.

My prediction: Git 3.0 ships in April 2027 with the SHA-256 default intact, GitHub announces general availability of SHA-256 repositories within a few weeks of that release, and by 2028 the majority of new repositories on the big forges are still SHA-1, because every large organization will have pinned the default back to what their tooling understands. Chacon's signed tree hash idea, or something like it, ends up in Git anyway, as the path that lets a SHA-1 repository pass a 2031 audit without a conversion. The expensive part is the decade of running two formats side by side.