跳转至

P2-14.2 分支(branch)、提交(commit)与文档可复现性

Section ID: P2-14.2 Version: v2026.09.15

分支与提交

Git 官方书将分支描述为指向提交的轻量指针。从同一个提交出发的两个分支,也可以各自积累不同的提交,形成不同的历史线。

在文档项目中,分支有助于处理以下情况。

  • 区分正在编写的正文与已发布的正文。
  • 避免把实验性的目录修改立即反映到公开版。
  • 图片、代码和文档结构一起变化时,不把中间状态发布到网站。
  • 部署失败后追踪问题来自哪次修改。

分支名称本身不决定是否公开。哪条分支的修改会进入网站,由部署配置决定。

分支指向提交

假设 main 与 dev 都指向提交 A,此时在 dev 上创建新提交 B。dev 会移到 B,main 仍停留在 A。两个分支并没有把整个项目复制为两个独立文件夹,而是共享 A 之前的历史,只是现在指向不同提交。

flowchart TD
  A["提交 A"] --> B["提交 B"]
  M["main"] -.-> A
  D["dev"] -.-> B
  H["HEAD"] -.-> D

实线表示先有 A 再创建 B 的顺序,虚线表示分支和 HEAD 指向什么。A、B 是说明用的名称,不是在 Git 命令中使用的实际哈希。

用以下命令查看当前分支和提交连接。

git branch --show-current
git log --oneline --graph --decorate --all -5

第一个命令显示当前分支名,第二个显示最近五个提交的连接和分支名称。--all 查询多个引用可达的历史,并不是从远程服务器下载最新状态的选项。

在上一节的 git-record-practice 练习仓库中完成三个提交后,可以创建独立的工作分支。

1
2
3
4
git status --short
git switch -c revise-chart
git branch --show-current
git switch practice

在工作区干净的状态下执行,会从当前提交创建并切换到 revise-chart,然后返回 practice。还没有新提交时,两个分支指向同一个提交。相比之下,git branch revise-chart 只创建分支,不进行切换。

切换分支时,Git 会根据目标分支的文件状态更新工作区和暂存区。未提交的修改在条件允许时可能跟随到新分支;切换会覆盖修改时,Git 会拒绝操作。因此,不能把切换分支理解成“自动把未提交的修改存进另一个盒子”。

写作分支与部署分支

本书使用 dev 编写和编辑,使用 main 作为部署来源。这是本仓库的约定,不是 Git 为这些名称设定的功能。其他项目也可以使用一个分支或不同的名称。

flowchart TD
  A["在 dev 编写并提交"]
  B["检查正文、代码和图片"]
  C["将已检查的变更合入 main"]
  D["推送至 origin/main"]
  E["确认部署成功与页面内容"]

  A --> B --> C --> D --> E

写作分支记录正文、示例代码和图表的修改。部署分支可以维护为指向选定公开状态的分支。

部署分支是标识发布来源的一种方式。在静态网站配置中,更新它可能触发部署。因此,将修改合入部署分支可能进一步更新公开文档。

提交、推送与部署

远程仓库是位于其他位置的 Git 仓库。origin 是为远程地址设置的惯用别名,不等于 GitHub 服务本身的名称。

操作 改变的对象 尚未保证的结果
在本地 commit 本地历史与当前分支 远程更新
向远程 push 远程分支及所需的 Git 对象 网站部署成功
执行部署 构建并发布网站的过程 正文数值与说明正确

已配置远程地址且有写入权限时,以下命令会把本地 dev 推送到 origin 的 dev。上面的练习仓库没有配置远程,因此尚不具备直接执行该命令的条件。

git push origin dev

远程存在本地尚未包含的提交时,普通 push 可能被拒绝。应先查看远程历史并整合变更,再次推送。仅切换到本地 main 不会把 dev 的修改合入。结合两条历史中变更的操作称为合并(merge);同一位置被改成不同内容时,可能需要人工解决冲突。

将相关文件归入同一变更

提交可以记录尚未完成的工作。选择要发布的提交时,需要检查正文与相关资源是否一致。

例如,编写 P2-13.3 时,以下文件可能一起变化。

文件类型 示例 一起检查的理由
正文 section-03.md 读者阅读的文字
图片生成代码 p2_13_3_compare_and_save.py 重新生成图片的来源
图片 subplot-loss-accuracy-zh.svg 及各语言 SVG 插入正文的结果
来源记录 正文参考资料及必要的依据笔记 支持说明与范围判断
网站导航设置 导航配置文件 在发布文档中显示的路径

这些文件彼此关联时,放在同一个提交中很自然。同一时间进行的独立 CSS 布局修改,另做提交会更容易追踪。

文档可复现性

在软件中,可复现性(reproducibility)常指使用相同代码和环境,再次得到相同结果的能力。本书对文档可复现性的理解稍宽一些。

文档可复现性应能回答以下问题。

  • 这段说明依据了什么?
  • 正文中的图表由什么代码生成?
  • 示例代码要求哪些包版本?
  • 这一节在什么时候进入发布目录?
  • 错误由哪个提交引入,又由哪个修正提交纠正?

因此,可复现性不只是正文的问题。正文、代码、图片、调查笔记和部署配置需要一致。使用同一提交中的正文与生成代码,并匹配所需数据、包版本和设置,才能追踪重新生成过去文档结果的条件。

提交固定的是已记录的文件,不会自动保存虚拟环境、已安装字体或外部数据。例如,相同图表代码在不同 Matplotlib 或字体版本下,可能产生不同的字宽和布局。使用随机数时还要记录种子,但单个种子并不能保证所有环境都产生相同文件。

复现对象 需要一并记录的条件 比较结果
计算值 代码、输入数据、包版本、设置 数值、数组形状、容许误差
图表外观 计算条件、字体、坐标范围、尺寸 曲线、标签、图例、裁切
文件字节 连同渲染器版本和元数据一起固定 文件哈希

P2-13.3 的脚本可以把图表生成到独立文件夹,而不覆盖正文资源。在仓库根目录执行,使用已安装 Matplotlib、NumPy 和默认字体 Noto Sans CJK JP 的 Python 环境。用 --font-family 选择其他字体可能改变外观。

图表生成代码

python docs/assets/part-02/chapter-13/p2_13_3_compare_and_save.py --language all --output-dir .tmp/p2-14-reproduce

这会生成三种语言共六个 SVG 文件。把其中的 subplot-loss-accuracy-zh.svg 与正文图片比较时,不仅要确认文件存在,还要检查最终准确率、坐标范围和图例。相同环境下也可以比较文件哈希;哈希不同时,先区分数值变化与格式变化。

发布前检查连接关系

部署之前,至少检查以下连接。

对象 检查问题
Markdown 正文 图片和内部链接是否指向实际文件?
网站导航 新文档是否已加入 nav?
示例代码 正文代码与生成脚本是否一致?
图片 是否有裁切、重叠或误导性的展示?
来源记录 来源是否支持正文主张?
构建 mkdocs build 是否通过?

否则,在部署分支发布后,页面可能出现失效链接、图片缺失或说明与示例不一致。

案例 1. 正文是 0.86,图片却是 0.88

假设已发布文档的图表中,最终准确率是 0.88。在写作分支中,将最终准确率改为 0.86,并把正文改成“最后三个训练轮次的准确率保持 0.86”。即使修改了生成代码,如果没有重新生成图片,正文与图表仍然描述不同结果。

状态 正文 生成代码 图片
原公开版 最终准确率 0.88 最终值 0.88 最后一点 0.88
修改中 最终准确率 0.86 最终值 0.86 最后一点 0.88
检查完成 最终准确率 0.86 最终值 0.86 最后一点 0.86

写作分支中的中间提交有助于保存修改过程。发布前要运行生成代码,更新图片,并确认正文引用该文件。网站构建成功不等于自动验证了数值一致性。

如果部署由向特定分支的 push 触发,那么把已检查状态合入该分支并推送到远程时,部署任务就会启动。仅有本地提交不会改变公开网站。需要确认任务成功及页面实际展示的结果,才能判断公开状态。

亲自选择修改文件

假设正文与代码中的最终准确率都已改成 0.86,尚未重新生成图片,还独立修改了 CSS 颜色。请选择“修正准确率说明”提交应包含的文件。

  1. 判断旧图片是否仍与说明一致。
  2. 重新生成图片后,将正文、代码和对应图片一起选择。
  3. 判断 CSS 修改是否独立于准确率说明。

此时需要更新图片,独立的 CSS 修改则另做提交。即使把准确率修改的提交 push 到 dev,如果部署只连接 main,公开网站仍然是之前的状态。

检查清单

  • 能把分支描述为区分工作流的有名字的历史线吗?
  • 能解释写作分支和部署分支的角色吗?
  • 能解释为什么提交应按目的组织变更吗?
  • 能根据目的选择同一提交中的文件吗?
  • 能解释为什么可复现性需要正文、代码、图片、调查笔记和导航保持一致吗?
  • 能说明为什么更新部署分支需要做出发布判断吗?
  • 能解释中间提交与待发布提交的检查范围为何不同吗?
  • 能解释为什么刚创建的两个分支可以指向同一个提交吗?
  • 能区分提交、推送、部署,以及切换与合并吗?
  • 能解释为什么只记录代码提交,不能保证安装环境与图片复现吗?
  • 能说明部署前为什么需要检查导航、图片、调查笔记和构建吗?

来源与参考资料