bigywater.tech
Git · 11

SHA-256 仓库:object-format 不同的仓库结构有什么变化

SHA-256 仓库和普通仓库有什么不同?这篇在同一份内容上创建两种仓库,对比配置、hash 长度、tree 和 index 的字节数,手算 SHA-256 的 blob hash,最后试试两种仓库能不能互相 fetch。

64 位
SHA-256 仓库的 hash 长度(SHA-1 是 40 位)
359 → 479
同样 10 个文件,tree 对象解压后的字节数
mismatched
两种格式互相 fetch 的结果:fatal: mismatched algorithms

创建时决定

实测 · 本机执行输出
  [sha1]
    $ git rev-parse --show-object-format; git config --local --list | grep -E "repositoryformatversion|objectformat" || true
    sha1
    core.repositoryformatversion=0
  [sha256]
    $ git rev-parse --show-object-format; git config --local --list | grep -E "repositoryformatversion|objectformat" || true
    sha256
    extensions.objectformat=sha256
    core.repositoryformatversion=1

git init --object-format=sha256 决定整个仓库的哈希算法,写进 extensions.objectformat,并把 core.repositoryformatversion 提到 1。之后无法改变。

hash 变长

实测 · 本机执行输出
  [sha1] HEAD = 5bda956e00d5b8a1079763653230b1007eaac8a6  (40 位十六进制)
  [sha256] HEAD = 21e5ed726238c38fbc7e807fc88d94ea828ed649a5f048027def37a98c0fdfa9  (64 位十六进制)
  $ find .git/objects -type f | head -3
  .git/objects/95/af096e0de45efede313bca8272ccf0194f5e067a8ceca790bdb40099c66bee
  .git/objects/a3/5f338c4e3f3d62632a3413b62bf1761b0f65e638e03566303b266eb7985130
  .git/objects/eb/6216fa5957e18a0e6ed849dd06c22fde18d084356aaf8d551e89fdb3011489
  $ git log --oneline -1; git log --abbrev=10 --oneline -1
  21e5ed7 提交
  21e5ed7262 提交

hash 从 40 位十六进制变成 64 位,松散对象的文件名也变成“2 位目录加 62 位文件名”。git log 的默认缩写仍然是 7 位。

公式不变

实测 · 本机执行输出
  git:  a35f338c4e3f3d62632a3413b62bf1761b0f65e638e03566303b266eb7985130
  手算: a35f338c4e3f3d62632a3413b62bf1761b0f65e638e03566303b266eb7985130
  一致: True

对象格式没有变,仍是“类型 长度 NUL 内容”,只是换了 SHA-256。手算 blob 的 hash 与 git 一致。

体积

实测 · 本机执行输出
  [sha1] tree 解压后 359 字节,头部 "tree 350",10 个条目,每个条目的 hash 占 20 字节
  [sha256] tree 解压后 479 字节,头部 "tree 470",10 个条目,每个条目的 hash 占 32 字节

tree 条目的 hash 从 20 字节变成 32 字节,10 个条目的 tree 从 359 字节变成 479 字节;索引文件也相应变大。仓库里 hash 出现的地方都会变大,但相对于文件内容本身通常很小。

索引与对象总大小

实测 · 本机执行输出
  [sha1] .git/index = 786 字节,tree 对象解压后 359 字节
  [sha256] .git/index = 970 字节,tree 对象解压后 479 字节

同样 10 个文件,.git/index 从 786 字节增加到 970 字节。

互不兼容

实测 · 本机执行输出
  $ git fetch /work/l7sha1 main 2>&1 | head -5
  fatal: mismatched algorithms: client sha256; server sha1
  $ git fetch /work/l7sha256 main 2>&1 | head -5
  fatal: mismatched algorithms: client sha1; server sha256
  $ git clone -q /work/l7sha256 l7clone 2>&1 && git -C l7clone rev-parse --show-object-format
  sha256

两种仓库之间不能 fetch / push,会立刻报 mismatched algorithms。clone 一个 sha256 的远程会自动得到 sha256 的本地仓库。这就是 SHA-256 仓库在实际使用中要考虑的最大障碍:服务器、客户端和工具链都要支持。

分步演示

SHA-256 仓库
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / git 2.54.0(Apple Git-157);每个实验在临时目录里新建仓库,HOME 和全局配置指向实验专用的空目录(不读用户自己的 git 配置),提交的作者与时间固定以便复现;需要网络协议的实验用本机的 file:// 或 git daemon 回环端口(9800 以上),不碰任何远程仓库;计时用 time.perf_counter,数字每次运行会有小幅抖动。两个仓库内容与作者时间完全相同;字节数是对象解压后的长度和 .git/index 文件大小
    • 没有验证:compatObjectFormat(两种哈希之间的映射,新版本的过渡功能,本文没有启用);主流托管服务和各种工具对 SHA-256 仓库的支持;SHA-256 的性能与 SHA-1(SHA1_DC)的比较;在 sha256 仓库里使用 GPG / SSH 签名的行为
    京ICP备2026067502号-1京公网安备11010502063487号