首页
/ 为 Material for MkDocs 贡献代码:从 Fork 到合入的 Pull Request 完整实操指南

为 Material for MkDocs 贡献代码:从 Fork 到合入的 Pull Request 完整实操指南

2026-09-10 12:27:41作者:滕妙奇

Material for MkDocs 是一个活跃维护、持续演进的开源项目,任何人都可以通过提交 Pull Request(PR)贡献 bug 修复、文档改进或新功能。本文以仓库中的贡献指南 making-a-pull-request.md 为骨架,完整讲解从创建 Fork、搭建开发环境、topic 分支开发、合并上游并发变更,到创建草稿 PR、接受评审、最终合入的每一步细节;同时结合仓库中的开发环境配置(customization.md)、构建脚本(package.json)与内置 info 插件(src/plugins/info/plugin.py)源码,为你提供一份可直接照着执行、经得起评审检验的贡献指南。

贡献前的第一原则:先讨论,再动手

在投入精力修改代码、创建 PR 之前,请务必先在社区里说明你的意图。这是整个贡献流程的起点,能避免大量返工:

  • 如果你认为发现了 bug,请先提交一份 bug 报告
  • 如果你打算改进文档,请先创建一个 文档问题
  • 如果你想开发新功能,请先提交一份 变更请求

请认真参考这些指南给出的建议。你要解决的问题,可能已经存在更简单的解法,也可能通过配置或 定制化 就能实现,未必需要改动项目源码。项目整体的贡献入口与各类模板的选择,可以参考 贡献总览

先掌握 Pull Request 的基础知识

Pull Request 是 Git 托管服务(本项目使用 GitHub)在 Git 之上封装的一种协作概念。开始之前,建议先熟悉 GitHub 官方文档中的几篇文章:

  1. Forking a repository(Fork 仓库);
  2. Creating a pull request from a fork(从 Fork 创建 PR);
  3. Creating a pull request(创建 PR)。

这些官方文章针对不同操作系统和不同的 GitHub 交互方式提供了定制化说明。本指南描述的是适用于 Material for MkDocs 的流程,无法覆盖所有工具组合与操作方式的排列组合,因此理解 PR 的一般概念是继续的前提。

Pull Request 全流程总览

先建立 3 万英尺的整体视角,再进入具体命令。整个流程分为两个阶段:准备变更并创建草稿 PR,以及收尾评审并合入

准备变更与创建草稿 PR

下面的时序图描述了准备 PR 时各仓库之间典型的流转关系:在主仓库 Fork 出你的仓库 → clone 到本地 → 创建 topic 分支 → 迭代编辑与推送 → 同步上游变更 → 创建草稿 PR 并接受评审。

sequenceDiagram
  autonumber

  participant mkdocs-material
  participant PR
  participant fork
  participant local

  mkdocs-material ->> fork: fork on GitHub
  fork ->> local: clone to local
  local ->> local: branch
  loop prepare
    loop push
      loop edit
        local ->> local: commit
      end
      local ->> fork: push
    end
    mkdocs-material ->> fork: merge in any changes
    fork ->>+ PR: create draft PR
    PR ->> PR: review your changes
  end

具体步骤如下:

  1. 创建 Fork:Fork 一份 Material for MkDocs 仓库,得到一份你有权限推送的仓库副本。注意:同一个仓库在同一时间只能存在一个 Fork,你创建的 Fork 就是"你的那一个"。
  2. Clone 到本地:把 Fork 克隆到本地机器,开始修改工作。
  3. 创建 topic 分支:所有贡献都应通过一个名称能描述所做事宜的 topic 分支进行。这允许你同时进行多项工作,如果与公共版本协作,也能让他人明确看到这些代码是进行中的工作。topic 分支生命周期相对短暂,当你的变更被并入代码库后它就会消失。
  4. (如需改代码)搭建开发环境:如果打算修改代码(而不仅是文档),需要先 搭建开发环境;下面有完整步骤。
  5. 迭代编辑与提交:编辑、提交是迭代过程。请以"合理的块"为单位提交——每个 commit 代表一段完整的工作,而不是一次性把所有内容堆进一个提交。细粒度、增量式的提交远比"一次提交、四处开花、牵涉大量文件"的大变更容易评审。尽量让变更保持小且局部化,提交时始终想着评审者,尤其要写有意义的提交信息。
  6. 定期推送:把工作定期推送到你的 Fork。
  7. 同步上游变更:随时关注所克隆的 Material for MkDocs 仓库的变化。如果工作周期较长,这一点尤其重要——请定期把并发产生的变更合并进你的 Fork 和分支。创建 PR 之前至少必须做一次,越频繁越好,以把冲突风险降到最低。
  8. 创建草稿 PR:当变更处于"你能在草稿 PR 中描述它们"的状态时,创建草稿 PR,并引用促成这项工作的任何既有讨论或 issue。草稿是尽早从维护者或其他贡献者获得反馈的好方式,你可以在你认为重要的节点显式请求评审。
  9. 自查并迭代:把自己当作评审者审查自己的工作,修复发现的问题。批判性地查看所改文件的 diff,特别关注变更是否尽可能小、是否符合项目通用编码风格。收到反馈后,按需对上述流程迭代。

补充验证:提交前至少用若干项目验证变更。必须确保不破坏 Material for MkDocs 自身文档的构建(文档位于仓库的 docs 目录),同时可选用示例项目验证相关示例仍能正常构建。

收尾:正式评审与合入

当你满意于自己的变更时,进入收尾阶段——把 PR 正式化并请求更正式、更详细的评审。

sequenceDiagram
  autonumber
  participant mkdocs-material
  participant PR
  participant fork
  participant local

  activate PR
  PR ->> PR : finalize PR
  loop review
    loop discuss
      PR ->> PR: request review
      PR ->> PR: discussion
      local ->> fork: push further changes
    end
    PR ->> mkdocs-material: merge (and squash)
    deactivate PR
    fork ->> fork: delete branch
    mkdocs-material ->> fork: pull
    local ->> local: delete branch
    fork ->> local: pull
  end
  1. Finalize(正式化):当你确信所作变更足以构成维护者可并入代码库的贡献时,将 PR 正式化。这向所有人表明你认为工作"完成",可以进入接受与合入视角的评审。
  2. 请求评审:向维护者请求评审。
  3. 讨论与修改:维护者可能对你的代码发表评论,请与他们讨论。注意维护者的视角可能与你不同——他们更多从项目长期维护的角度出发,而你更聚焦于自己解决的具体问题或特性。请始终保持相互尊重的讨论。
    • 请理解:并非所有 PR 都会被并入代码库。原因多种多样:工作可能暴露出阻碍合入的其他问题;有时它揭示了更好的做法,或说明需要更通用的方案。这些都正常,即使具体变更最终未被接受,也有助于项目前进。
  4. 按反馈迭代:把要求的修改提交到本地 clone 并推送到 Fork,PR 会自动更新。一个贡献可能需要多次迭代才能达到可接受状态。认真阅读每条评论、谨慎修改,能显著加快流程。
  5. 合入(可能 squash):评审者完全满意后,将变更合入主分支。过程中评审者可能把多个 commit squash(压缩) 成更少的提交,并可能编辑提交信息。恭喜——你现在已经为项目做出了贡献,变更会以你的名义出现在主分支中。
  6. 清理:你可以删除 Fork 和本地仓库,下次重新开始;也可以保留它们,但后续任何工作都必须与上游保持同步。推荐从删除 Fork 上的分支开始。
  7. 同步合并结果:为确保拿到你产出的变更,把主仓库的变更 pull 到 Fork 的 master 分支。
  8. 删除本地 topic 分支:同样从本地 clone 中删除 topic 分支。
  9. 同步本地 master:把变更 pull 到本地 clone 的 master 分支。

分步实操指南

下面是具体指令与技巧。本指南默认使用 Git 命令行工具;对于大多数替代方案(IDE、GitHub 网页界面提供的功能),从命令行指令转换过去并不困难,仅在必要时补充说明。

Fork 仓库

要对 Material for MkDocs 做修改,先在 GitHub 上 Fork 其仓库,这样你就拥有一个可推送变更的 GitHub 仓库(只有维护者和协作者对原始仓库有写权限)。

无论修改代码还是文档,都请 Fork 该仓库。建议把仓库名追加 -fork 后缀,让看到它的人明白这是一个临时 Fork 而非原始仓库或项目的长期分支;也可以加一段说明用途的描述。

搭建开发环境

从这一步开始,请完整执行开发环境搭建流程(原始指南指向 customization.md#environment-setup,此处展开完整命令),以便在可修改、可评审、可测试的环境中工作:

  1. 克隆仓库

    git clone https://github.com/squidfunk/mkdocs-material
    cd mkdocs-material
    
  2. 创建并激活 Python 虚拟环境

    python -m venv venv
    source venv/bin/activate
    

    !!! note "确保 pip 始终在虚拟环境中运行" 设置环境变量 PIP_REQUIRE_VIRTUALENV=true 后,pip 会拒绝在虚拟环境之外安装任何东西。忘记激活 venv 会随着时间在环境外安装各类包,可能引发更多错误。建议把它写进 .bashrc.zshrc 并重启 shell:

    ```
    export PIP_REQUIRE_VIRTUALENV=true
    ```
    
  3. 安装 Python 依赖gitrecommendedimagingpyproject.toml 中定义的扩展依赖组,imaging 用于社交卡片等图片生成):

    pip install -e ".[git, recommended, imaging]"
    pip install nodeenv
    

    此外还需在系统中安装 cairopngquant 库,具体见 image-processing.md 说明。

  4. 安装 Node.js 与前端依赖:把 Node.js LTS 版本装进 Python 虚拟环境,再安装全部 Node 依赖:

    nodeenv -p -n lts
    npm install
    
  5. 进入开发模式:一个终端运行 watcher 持续编译主题源码:

    npm start
    

    另一个终端启动 MkDocs 实时预览服务器:

    mkdocs serve --watch-theme
    

    浏览器访问 localhost:8000 即可看到本项目文档的实时构建。

    !!! warning "不要修改 material 目录" 永远不要在 material 目录中做任何修改——该目录的内容由 src 目录自动生成,主题构建时会整体覆盖。

  6. 构建主题:完成修改后,执行 npm run build 触发所有样式表与 JS 文件的编译和压缩,产物位于 material 目录;再运行 mkdocs build 就能看到你的改动生效。如果改了项目自身的 overrides(比如提交 PR 前),需要构建全部内容,用 npm run build:all(耗时更长,会额外构建图标搜索索引、schema 文件以及附加样式与脚本)。

    !!! note "源码布局与自检" 主题真正的源码在 src/templates(含 main.scssbundle.ts)与 src/pluginspackage.json 还提供了 npm run check(TypeScript 类型检查 check:build 与 stylelint/eslint 风格检查 check:style)用于提交前自检。

修改代码与文档

修改代码或文档时,请遵循项目既有风格:这能提高可读性,也让评审者更容易读 diff。避免做大规模风格变更,比如让 IDE 重新格式化所有代码。

动手修改前,认真研究你要改动的代码,确保完全理解其工作原理。这不仅能帮你解决问题,也能把产生非预期副作用的概率降到最低。

提交到分支

PR 的开发最好放在独立于 master 的 topic 分支上进行。创建新本地分支并提交:

git switch -c <name>

推送到 Fork 时使用:

git push -u origin <name>

-u--set-upstream 的简写,它让新分支"跟踪"Fork 中同名的分支——之后默认的 pullpush 都会作用于 Fork 里的那个分支。

合并并发变更

工作周期越长,主仓库在此期间产生新变更的概率越大。建议把原始 Material for MkDocs 仓库设置为本地 clone 的 upstream 远端:

$ git remote -v
origin	git@github.com:<your_username>/mkdocs-material-fork.git (fetch)
origin	git@github.com:<your_username>/mkdocs-material-fork.git (push)
$ git remote add upstream https://github.com/squidfunk/mkdocs-material.git
$ git remote -v
origin	git@github.com:alexvoss/mkdocs-material-fork.git (fetch)
origin	git@github.com:alexvoss/mkdocs-material-fork.git (push)
upstream	https://github.com/squidfunk/mkdocs-material.git (fetch)
upstream	https://github.com/squidfunk/mkdocs-material.git (push)

之后就能直接把并发变更从 upstream 拉到本地 clone,在本地完成必要的合并,再推送到你的 Fork。注意 pull 时必须显式指定远端:

# 先在本机做并提交一些本地修改
push pull upstream master

这条命令把 master 分支的变更拉进你的 topic 分支并合并它们。

测试与审查变更

提交任何变更之前,必须确认其行为符合预期且不产生非预期副作用。至少在以下三组冒烟测试上验证:

  • 项目自身文档:按 customization.md#environment-setup 搭好环境后,mkdocs serve 应持续构建文档。检查没有错误信息,理想情况下也没有(新增的)警告。
  • 一个代表问题或新特性的测试项目:如果你为 bug 提交过报告,可能已有 minimal reproduction(最小复现)。开发新功能时,可能需要新建一个项目充当测试套件——它还能兼作文档,展示新功能预期如何工作。
  • 相关示例项目:用示例项目中的相关示例验证。

关于最小复现,仓库内置的 info 插件可以帮你自动生成。按 info.mdmkdocs.yml 中启用 plugins: - info 后运行 mkdocs build,插件会把相关文件打包成 example.zip 并打印清单,直接可附到 bug 报告中。其实现位于 src/plugins/info/plugin.py:归档功能由 src/plugins/info/config.py 中的 archive(默认 true)与 archive_stop_on_violation(默认 true)两个开关控制,打包完成后进程随即退出。创建复现的完整步骤(升级到最新版、mkdocs new . 引导项目、最小化配置、剔除所有非必要文件)见 creating-a-reproduction.md

创建 Pull Request

最初请以草稿(draft)形式创建 PR,通过 GitHub 提供的各种界面完成即可——GitHub 已提供必要的信息,此处不再赘述各界面操作。

提交信息、错误与 squash

  • 提交信息要有意义:让评审者(以及未来的维护者)能从提交信息看出这段变更做了什么、为什么做。
  • 提交粒度要:一次提交对应一件完整的小事,方便逐段审查与回滚。
  • 合入时评审者可能 squash 你的多个提交,并编辑提交信息——这是项目合入流程的一部分(见上文时序图),提交历史会在合入时被整理得更简洁。

删除分支

PR 合入 master 后,应同时删除 Fork 上(GitHub)与本地 clone 中的分支,避免对开发状态产生混淆。先切回 master:

git switch master
git branch -d <name>

后续 Pull Request

后续 PR 必须从最新的 master 历史开始。一种简单做法是删除 Fork,下次重新 Fork;如果贡献频繁或连续做多个 PR,也可以只做同步:用 GitHub 界面同步 Fork 并 pull 到本地,删除上次的 topic 分支(本地与 Fork 都要),再从主仓库的 master pull 到本地 master,然后开始新工作。

应做与不应做

  1. 不要 不做任何解释就提交一个 PR。
  2. 先在讨论区说明你的意图,让任何变更的理由在写代码之前就清晰。
  3. 在 PR 中链接相关的讨论或 issue,提供上下文。
  4. 对任何不确定的事情提问。
  5. 扪心自问:你的工作是否惠及更广泛的社区、让 Material for MkDocs 变得更好。
  6. 权衡变更的成本与收益:有些看似合理的变更会引入较多复杂度却收益有限,可能破坏既有行为,或在后续其他变更时变得脆弱。
  7. 频繁合并并发变更,把难以解决的冲突风险降到最低。

仓库内可继续深挖的线索

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.16 K
2.78 K
kernelkernel
deepin linux kernel
C
34
18
docsdocs
暂无描述
Markdown
904
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
932
1.86 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
862
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.95 K
1.03 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.38 K
1.47 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
535
606
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
549
398
leetcodeleetcode
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Markdown
77
23