Mermaid GitGraph 图完全指南:从 commit/branch/merge 语法到主题变量的源码级解析
【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaid
本文基于 Mermaid 仓库的官方语法文档 gitgraph.md 展开,系统讲解 Git Graph 图的声明式语法——commit、branch、checkout、merge、cherry-pick五大操作,全部gitGraph配置项(showBranches、mainBranchName、parallelCommits等)、LR/TB/BT方向控制与git0~git7系列主题变量。结合 packages/mermaid/src/diagrams/git/gitGraphAst.ts 等源码,你将既会写图,也能理解每个语法糖背后的状态机与校验规则。
什么是 Git Graph 图
Git Graph 是对 Git 提交与 Git 操作(命令)在各分支上的图形化表示。这类图对开发者和 DevOps 团队分享 Git 分支策略特别有用,例如直观展示 Git Flow 的工作方式。
一个最基础的示例,标题通过 front matter 的title指令设置:
Mermaid 支持四个基本 Git 操作:
commit:在当前分支上表示一次新提交;branch:创建并切换到新分支,将其设为当前分支(等价于 git 中创建分支并 checkout);checkout:切换到已存在的分支,并将其设为当前分支(checkout与switch可以互换使用);merge:把一个已存在的分支合并进当前分支。
借助这几个关键命令,你可以非常快速地在 Mermaid 中画出 Git 图。
从源码结构看,GitGraph 图由 gitGraphDiagram.ts 注册为标准的DiagramDefinition:解析器(gitGraphParser.ts,由 Jison 生成)、数据模型(gitGraphAst.ts导出的db对象)、渲染器(gitGraphRenderer.ts)与样式(styles.js)各司其职。所有状态都收敛在 gitGraphAst.ts 的一个ImperativeState中,包含commits(提交映射)、branches(分支到 HEAD 提交的映射)、currBranch(当前分支)、direction(方向,默认'LR')与自增序号seq等字段,这正是"每条命令按书写顺序依次作用"这一声明式语义的实现基础。
声明式语法与初始状态
GitGraph 语法非常直接:它是一种声明式写法,每个提交按其在代码中出现的顺序依次画在时间线上,即按插入顺序逐条执行命令。
第一步是用gitGraph关键字声明图类型,它告诉 Mermaid 你要画一张 Git 图并按此解析后续代码。
每个 Git 图都从main分支初始化,因此除非创建其他分支,提交默认都会落在main上——这与 Git 本身的工作方式一致(最初总是从 main 分支,即旧称的 master 分支开始),并且main分支默认就是当前分支。
三个提交都落在默认main分支上的最小图:
仔细观察上面的图:默认分支main上有三个提交,并且每个提交都被赋予了唯一且随机的 ID。源码印证了这一点:当未提供id时,commit 函数 生成的 ID 是seq + '-' + 7位随机串(随机串由 getID() 产生)。
自定义 commit ID
声明提交时可以用id属性指定自定义 ID,格式为id:加双引号包裹的值,例如commit id: "your_custom_id":
在实现中,commit会把id与msg统一经过common.sanitizeText清洗;若 ID 已存在,源码只记录 warn("Commit ID ... already exists"),不会中断渲染。
修改 commit 类型
Mermaid 中提交有三种类型,在图中的图形略有差异:
NORMAL:默认提交类型,实心圆表示;REVERSE:强调某次提交为"回退提交",带叉的实心圆表示;HIGHLIGHT:高亮某次提交,实心矩形表示。
用type属性声明,例如commit type: HIGHLIGHT。未指定时默认取NORMAL。三种类型与自定义 ID 组合的示例:
添加 Tag
你可以像 Git 中的 tag/release 概念一样,用tag属性给提交打标签:commit tag: "your_custom_tag"。id、type、tag这些属性可以在同一条提交声明中任意混搭:
创建新分支
使用branch关键字并给出新分支名。分支名必须唯一,不能与已有分支重名;如果分支名容易与关键字混淆,需要用""引号包裹。用法示例:branch develop、branch "cherry-pick"。
Mermaid 读到branch时会创建该分支并将其设为当前分支,等价于 Git 中"创建并切换"。这一点在源码 branch 函数 中可以直接看到:它先校验重名(抛出 "Trying to create an existing branch..." 错误),然后把新分支的 HEAD 指向当前head,最后自动调用checkout(name):
起始于默认main分支并推送两个提交;创建develop分支后,其成为当前分支,之后的所有提交都落在develop上。
切换(checkout)已存在分支
使用checkout关键字并给出一个已存在的分支名;若找不到该分支会报控制台错误。用法示例:checkout develop。
源码 checkout 函数 的校验逻辑:分支不存在时抛出 "Trying to checkout branch which is not yet created" 错误;存在时更新currBranch,并把head定位到该分支记录的 HEAD 提交(若该分支尚无提交则head置为 null)。
在上一例基础上,用checkout main把当前分支切回main,其后的两个提交注册到main上。
合并两个分支
使用merge关键字并给出要合并进来的分支名。找不到该分支会报错;只能合并两个不同的分支,不能把一个分支合并到自身(会抛错)。用法示例:merge develop。
Mermaid 读到merge时,找到目标分支及其 HEAD 提交,把它与当前分支的 HEAD 提交连接,每次合并都会产生一个合并提交(merge commit),图中以实心双圆表示。
merge 函数 的校验链相当严格,与文档描述的规则一一对应:
- 当前分支与目标分支是同一分支 → "Cannot merge a branch to itself";
- 当前分支没有任何提交 → "Current branch (...) has no commits";
- 目标分支不存在 → "Branch to be merged (...) does not exist";
- 目标分支没有任何提交 → "Branch to be merged (...) has no commits";
- 两个分支 HEAD 相同 → "Both branches have same head";
- 自定义
id与已有提交 ID 冲突 → 报错并要求换一个唯一 ID。
develop被合并进main,产生一个合并提交;当前分支仍是main,最后两个提交注册到main。
合并提交也可以像提交一样装饰属性,可以一个都不用、部分用或全用:
id:用自定义 ID 覆盖默认 ID;tag:给合并提交添加自定义 tag;type:覆盖合并提交的默认形状(使用前面提到的 commit 类型)。
例如:merge develop id: "my_custom_id" tag: "my_custom_tag" type: REVERSE。下面是一个多分支交叉的完整例子,最后一行演示了带属性的合并:
从其他分支 cherry-pick 提交
与真实 Git 类似,Mermaid 支持用cherry-pick关键字把另一个分支上的提交摘到当前分支。必须用id属性给出要摘取的提交 ID:cherry-pick id: "your_custom_id"。执行后,当前分支上会创建一个代表 cherry-pick 的新提交,以樱桃图形高亮,并带有一个标注来源提交 ID 的 tag。
五条重要规则(与 cherryPick 函数 的校验逻辑一致):
- 必须提供已存在的提交
id,不存在则报错——因此要先用commit id:"..."的方式声明提交; - 被摘取的提交不能已存在于当前分支,cherry-pick 的提交必须来自其他分支;
- 当前分支在执行 cherry-pick 之前必须至少有一个提交,否则抛错;
- cherry-pick 合并提交时,
parent属性必填,省略或提供无效父提交 ID 都会抛错; - 指定的父提交必须是该合并提交的直接父提交(源码用
sourceCommit.parents.includes(parentCommitId)校验)。
示例:
源码层面还有一个细节:cherry-pick 生成的提交类型是commitType.CHERRY_PICK,若未显式提供 tag,会自动附加cherry-pick:<来源ID>(合并提交还会带|parent:<父ID>)作为 tag,这就是图中樱桃节点上出现来源标注的由来。
GitGraph 专属配置项
Mermaid 提供一组gitGraph配置项,可以在 front matter 的config指令中设置。完整清单:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
showBranches | Boolean | true | 设为false时图中不显示分支名与分支线 |
showCommitLabel | Boolean | true | 设为false时图中不显示提交标签 |
mainBranchName | String | main | 默认/根分支的名称 |
mainBranchOrder | Number | 0 | main 分支在分支列表中的位置,默认 0 即排在最前 |
parallelCommits | Boolean | false | 设为true时,距父提交 x 个距离的提交画在同一层,不体现时间先后 |
rotateCommitLabel | Boolean | true | 提交标签是否旋转 45 度(详见下文布局小节) |
这组配置的类型定义见 config.type.ts 中的GitGraphDiagramConfig,默认值由 schemas/config.schema.yaml 加载(defaultConfig.ts 中从 JSON Schema 读取),而运行时读取走 getConfig():用cleanAndMerge把默认值与用户通过mermaid.initialize()或 front matter 传入的gitGraph配置合并。单元测试 gitGraph.spec.ts 也逐条断言了showBranches、showCommitLabel、rotateCommitLabel、parallelCommits属性存在。
隐藏分支名和分支线
用showBranches: false隐藏分支名和线(渲染器 gitGraphRenderer.ts 在showBranches为真时才绘制分支元素):
提交标签布局:旋转或水平
Mermaid 支持两种提交标签布局,默认是旋转(rotated):标签放在提交圆下方并旋转 45 度,便于阅读,对长标签特别友好;另一种是水平(horizontal):标签水平居中放在提交圆下方,不旋转,适合短标签。用rotateCommitLabel关键字切换,默认true(旋转)。
旋转布局:
水平布局(仅把rotateCommitLabel改为false,图体不变):
隐藏提交标签
用showCommitLabel: false隐藏提交标签。与上一节组合使用的示例(showBranches与showCommitLabel同时关闭):
自定义 main 分支名
用mainBranchName把默认分支改成任意字符串。下面把默认分支改名为MetroLine1,画了一张"想象中的地铁线路图":
注意这里checkout MetroLine1与merge MetroLine3、merge MetroLine2 tag:"MY JUNCTION"中的名字都必须与新分支名一致——从源码 状态初始化 可见,mainBranchName会同时决定初始currBranch与branchConfig的初始键。
自定义分支顺序
默认情况下,分支按它们在图中定义/出现的顺序展示。用order关键字(正整数)可以自定义顺序,写在分支定义后面:
Mermaid 遵循order的优先顺序规则:
- main 分支默认 order 为
0,永远最先展示(除非用mainBranchOrder配置改动它); - 未指定
order的分支,按出现顺序展示; - 指定了
order的分支,按order值排序展示。
要完全控制所有分支的顺序,必须为所有分支都定义order。
再看一个配合mainBranchOrder: 2的例子:
排序结果:test2、test3(未指定 order,按定义顺序)→test4(order 1)→main(order 2,因覆盖了mainBranchOrder而不再置顶)→test1(order 3)。
排序逻辑的实现在 getBranchesAsObjArray():未显式指定 order 的分支被赋予0.<索引>形式的浮点数(即"按出现顺序"排在前),再与显式 order 一起统一按数值升序排列——这解释了为什么"无 order 分支"整体排在"有 order 分支"之前。
方向控制:LR / TB / BT(v10.3.0+)
Mermaid 支持三种图方向:Left-to-Right(默认)、Top-to-Bottom、Bottom-to-Top。写法是在gitGraph关键字后加LR:、TB:或BT:。
左到右(默认,LR:)
默认方向是提交从左到右展开、分支上下堆叠。也可以显式写出LR::
上到下(TB:)
TB方向下提交从上到下展开,分支左右并排。在gitGraph后加TB::
下到上(BT:)(v11.0.0+)
BT方向下提交从下到上展开,分支左右并排。在gitGraph后加BT::
方向由解析器回调setDirection写入状态(初始值'LR'),渲染器根据direction决定坐标映射。
并行提交(v10.8.0+)
默认情况下 GitGraph 通过提交的水平位置传达时间信息:例如两个提交距父提交同样远时,先写的会画得更靠近父提交。开启parallelCommits: true可关闭这种时间差——距父提交 x 个距离的提交会画在同一层。
时间顺序模式(默认,parallelCommits: false):
并行模式(parallelCommits: true):
主题与主题变量
Mermaid 支持预定义主题,也可以用主题变量覆盖任何主题的既有取值。GitGraph 可用的预定义主题:base、forest、dark、default、neutral。切换主题可以用initialize调用或 front matter 指令(directives 说明),主题机制详见 theming 文档。
以同一张多分支图分别套用不同主题为例(theme: 'base'/'forest'/'default'/'dark'/'neutral'只需替换 front matter 中的theme值):
用主题变量定制外观
主题变量控制图各元素的颜色与排版。以default主题为基准示例,覆盖方式统一是 front matter 的themeVariables。
重要说明:主题变量最多覆盖8 个分支的颜色/样式,超出后循环复用——第 9 个分支使用第 1 个分支(索引 0)的取值。
分支颜色:git0~git7。git0驱动第 1 个分支,git1驱动第 2 个,依此类推:
分支标签颜色:gitBranchLabel0~gitBranchLabel7,规则相同:
由于只有 8 组标签变量,branch8、branch9会分别复用索引 0(main)与索引 1(branch1)的配色——即分支主题变量循环复用。
提交标签颜色与字号:commitLabelColor、commitLabelBackground、commitLabelFontSize:
Tag 标签:tagLabelColor、tagLabelBackground、tagLabelBorder控制 tag 的文字颜色、背景与边框;tagLabelFontSize控制 tag 字号:
高亮提交颜色:gitInv0~gitInv7按分支索引控制各分支上HIGHLIGHT提交的颜色(同样最多 8 个、循环复用):
仓库中的实现与测试索引
想在源码层面继续深入 GitGraph,可以从以下入口按调用链阅读(均在仓库相对路径下):
- gitGraphDiagram.ts:图定义注册(parser + db + renderer + styles);
- gitGraphAst.ts:命令执行与状态机核心,
commit/branch/merge/cherryPick/checkout的校验与合并配置逻辑; - gitGraphParser.ts:由 Jison 生成的语法解析器,负责把文本切分为命令并回调上述函数;
- gitGraphRenderer.ts:SVG 绘制,消费
showCommitLabel、rotateCommitLabel、parallelCommits、showBranches等配置; - gitGraphTypes.ts:
Commit、commitType(NORMAL/REVERSE/HIGHLIGHT/MERGE/CHERRY_PICK)等类型定义; - config.type.ts:
GitGraphDiagramConfig配置类型; - gitGraph.spec.ts:单元测试,覆盖各命令行为与配置读取;
- e2e/diagrams/gitgraph/:100 余个端到端渲染用例(
.mmd文件),覆盖 cherry-pick、merge 属性、order排序等场景,是观察各语法实际渲染效果的最好素材; - 本文依据的文档源文件位于 packages/mermaid/src/docs/syntax/gitgraph.md(docs/syntax/gitgraph.md 为其自动生成的站点版本)。
小结
GitGraph 图用不到十行声明式文本,就能表达 commit、branch、checkout、merge 与 cherry-pick 构成的完整分支协作流程;每个提交支持id/type/tag属性,每条branch支持order,gitGraph关键字支持LR:/TB:/BT:方向,front matter 的gitGraph配置节与git0~git7、gitBranchLabel*、commitLabel*、tagLabel*、gitInv*主题变量则覆盖布局、命名、排序与外观的全部定制需求。配合源码中的严格校验(重名分支、空分支合并、cherry-pick 父提交约束等),你在写图时遇到的每个报错都能在 gitGraphAst.ts 中找到对应逻辑。
【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaid
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考