研究 Git:分支只是指向提交的可移动引用

创建分支很快,因为它不需要复制整个工作目录。

edyang · 2015-01-15

创建分支很快,因为它不需要复制整个工作目录。真正被共享的是提交对象及其父子关系。

本文使用Git 2.x 与独立演示仓库。Git(分布式版本管理)保存提交对象和引用,工作区、暂存区与提交历史不是同一份状态。每次操作先判断它改变哪个区域,再决定是否适合当前协作情境。

1. 从现象推到机制

提交保存树对象、父提交和元信息。分支名指向一个提交,新提交使当前分支引用前进。两个分支共同指向的历史不会因此复制成两份,删除分支名也不等同立即删除所有对象。

研究 Git:分支只是指向提交的可移动引用的处理、反馈与观察关系

图中的四个节点分别表示提交对象、共同祖先、分支引用、引用移动。顺着实线检查输入如何变成输出,再沿虚线核对反馈条件。图示表达的是本文讨论的关系,不是实测曲线或现场截图。

2. 最小实现与输入条件

在临时仓库建立两条开发线,用图形日志观察共同祖先与分叉位置。提交内容与引用名称分开记,避免把某个分支名当成固定版本。

1
2
3
4
git branch demo-feature
git log --graph --oneline --all
git show --stat HEAD
git branch -v

示例在没有私人资料的临时仓库执行。先看 status、diff 与 log,再运行改变状态的命令;共享历史优先新增提交表达修复,不用改写历史掩盖已经发生的变化。

3. 用对照区分原因

下表列出需要主动改变的条件。预期行为来自机制分析,复现时还需记录运行环境和原始输出,不能将预期当作已经测得的结果。

改变的条件 需要验证的行为
两个分支指向同一提交 内容和历史起点可以完全相同
其中一条分支新增提交 只有相应引用向前移动
标签用于标记版本 仍要确认标签指向与类型

对照 1:两个分支指向同一提交

内容和历史起点可以完全相同。观察时记录各引用实际指向的提交号。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。

对照 2:其中一条分支新增提交

只有相应引用向前移动。观察时记录父提交和分支指针。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。

对照 3:标签用于标记版本

仍要确认标签指向与类型。观察时记录标签对象及目标提交。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。

4. 适用条件与取舍

引用名称便于交流,准确版本仍应使用提交标识。构建与部署回执记录分支名之外,还要记录实际提交,避免分支继续前进后含义改变。

一次正常运行只覆盖了这组输入。继续扩展前,应把上面的异常对照保留下来,尤其关注“标签用于标记版本”这一分支。后续方案若改变了图中任意一处依赖,原来的判断就要重新验证,不能仅凭界面相似或返回值相同沿用结论。

同月延伸

参考资料

  1. Pro Git 第二版
  2. Git 2.2.0 版本说明