跳转至

Refs

如果对象数据库回答的是“仓库里存了什么”,那么 refs 回答的就是“这些历史节点现在叫什么名字”。

ref 是什么

ref 本质上就是一个名字到对象 ID 的映射。
最常见的 ref 包括:

  • 分支;
  • 标签;
  • 远端跟踪分支;
  • HEAD

其中:

  • 分支通常指向 commit;
  • 轻量标签通常也直接指向 commit;
  • 附注标签 ref 先指向 tag 对象,再由 tag 对象指向目标对象。

为什么 ref 系统很重要

很多 Git 操作本质上都不是“改对象”,而是“移动名字”:

  • commit 生成新 commit 后,要更新当前分支 ref;
  • branch <name> 只是新建一个 ref;
  • tag 也是写 ref;
  • fast-forward merge 只是推进 ref;
  • reset --soft 主要也是改 ref。

如果 ref 系统设计不好,很多高层命令都会一起变得混乱。

HEAD 表示当前检出目标。
常见情况下它是一个符号引用,比如:

ref: refs/heads/main

这表示 HEAD 不是直接存一个 commit,而是指向某个分支。
当你 checkout 到一个裸 commit 时,HEAD 就会进入 detached 状态。

所以 HEAD 既是 ref 系统的一部分,又比普通 branch 更特殊。

为什么 ref 更新要加锁

refs 是高价值元数据。
如果改写时没有锁保护,可能出现:

  • 并发写覆盖;
  • 半写入;
  • 旧值被错误踩掉;
  • 分支历史丢失。

因此项目文档明确要求:

  • 写 ref 前先创建 .lock
  • 写完后原子替换;
  • 必要时校验预期旧值。

这类保护逻辑必须集中复用,不能每个命令自己发明一套。