修改文档文件夹架构
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
# pre-commit 自动化代码审查 — 部署与使用说明
|
||||
|
||||
> **生效前提**:本机已运行过 `pre-commit install`(钩子写入 `.git/hooks/`)。
|
||||
> 新机器/新开发者进入仓库后需执行一次 `pre-commit install`,详见「新机器启用」。
|
||||
|
||||
---
|
||||
|
||||
## 1. 部署架构
|
||||
|
||||
```
|
||||
git commit
|
||||
└─ pre-commit(.git/hooks/pre-commit)
|
||||
├─ trailing-whitespace 自动修复行尾空格
|
||||
├─ end-of-file-fixer 自动修复文件尾换行
|
||||
├─ check-added-large-files 阻止 >1MB 大文件
|
||||
├─ check-merge-conflict 阻止含冲突标记的文件
|
||||
├─ check-yaml 校验 YAML 语法
|
||||
├─ cppcheck C 静态分析(自有代码)
|
||||
└─ no-mojibake 阻止 U+FFFD 乱码文件
|
||||
└─ commit-msg(.git/hooks/commit-msg)
|
||||
└─ gitlint 校验 commit message 格式
|
||||
```
|
||||
|
||||
**两阶段钩子**:`pre-commit` 阶段拦截代码问题,`commit-msg` 阶段拦截格式问题。任一失败 → commit 中止。
|
||||
|
||||
### 依赖清单
|
||||
|
||||
| 组件 | 安装方式 | 用途 |
|
||||
|---|---|---|
|
||||
| pre-commit 4.6.2 | `uv tool install pre-commit` | 钩子框架 |
|
||||
| cppcheck 2.21.0 | `winget install cppcheck` | C 静态分析引擎 |
|
||||
| scripts/check_mojibake.py | 随仓库提交 | U+FFFD 乱码检测(纯 Python,无依赖) |
|
||||
|
||||
> **PATH 要求**:cppcheck 安装后需在系统 PATH 中(`C:\Program Files\Cppcheck`)。winget 自动写入 User PATH,但当前终端不会立即生效,需**重开终端**。
|
||||
|
||||
---
|
||||
|
||||
## 2. 各钩子规则详解
|
||||
|
||||
### 2.1 trailing-whitespace — 行尾空格清理
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| **触发条件** | 文件任意行末尾含空格或 Tab |
|
||||
| **处理方式** | **自动修复**(直接改写文件,删除行尾空白) |
|
||||
| **影响范围** | 所有被 git 跟踪的文件 |
|
||||
| **典型报错** | `Trim Trailing Whitespace` → `Fixing path/to/file.c` |
|
||||
| **修复方式** | 无需手动修复,钩子已自动改写;重新 `git add` 即可 |
|
||||
|
||||
> **注意**:首次对全库运行时,可能批量修改大量文件的行尾空格。这是正常行为,不会改变代码逻辑。
|
||||
|
||||
### 2.2 end-of-file-fixer — 文件尾换行
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| **触发条件** | 文件最后一行不是换行符(`\n`) |
|
||||
| **处理方式** | **自动修复**(在文件尾部追加换行) |
|
||||
| **典型报错** | `Fix End of Files` → `Fixing path/to/file.c` |
|
||||
| **修复方式** | 无需手动修复,钩子已自动改写;重新 `git add` 即可 |
|
||||
|
||||
### 2.3 check-added-large-files — 大文件拦截
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| **触发条件** | 单个文件 > 1MB(默认阈值) |
|
||||
| **处理方式** | **阻止提交**(需手动修复) |
|
||||
| **典型报错** | `ilerge file added: path/to/file.bin` |
|
||||
| **修复方式** | 确认文件是否应提交;若为构建产物则加入 `.gitignore`,若为必要大文件用 `--no-verify` 跳过 |
|
||||
|
||||
### 2.4 check-merge-conflict — 冲突标记拦截
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| **触发条件** | 文件含 `<<<<<<<`、`=======`、`>>>>>>>` 冲突标记 |
|
||||
| **处理方式** | **阻止提交** |
|
||||
| **修复方式** | 手动解决冲突后重新提交 |
|
||||
|
||||
### 2.5 check-yaml — YAML 语法校验
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| **触发条件** | `.yaml` / `.yml` 文件语法错误 |
|
||||
| **处理方式** | **阻止提交** |
|
||||
| **检查对象** | 主要校验 `.pre-commit-config.yaml` 本身 |
|
||||
| **修复方式** | 修正 YAML 缩进或语法后重新提交 |
|
||||
|
||||
### 2.6 cppcheck — C 静态分析
|
||||
|
||||
cppcheck 是开源 C/C++ 静态分析工具,**不运行代码**,通过语法分析和数据流推理发现潜在缺陷。本项目开启 `warning` / `performance` / `portability` / `style` 四个类别,任一类别发现问题即**阻止提交**(`--error-exitcode=1`)。
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| **触发条件** | 自有代码 .c 文件(App/、Src/、Inc/、Drivers/BSP/,第三方库除外)含潜在缺陷、冗余代码或可疑写法 |
|
||||
| **处理方式** | **阻止提交**(必须修复) |
|
||||
| **修复方式** | 按报告修复代码;确属误报用行内抑制 `// cppcheck-suppress` 或全局 `--suppress` |
|
||||
| **典型报错** | `[path/to/file.c:123]: (style) variableScope The scope of the variable ... can be reduced` |
|
||||
| **增量速度** | 单文件约 1~2 秒;全库约 5 秒 |
|
||||
|
||||
> **完整规则清单(style 类别 95 项详解)、配置参数、YAML 引号陷阱、误报抑制方法、历史问题处理记录见 `docs/cppcheck使用说明.md`。**
|
||||
|
||||
### 2.7 no-mojibake — U+FFFD 乱码拦截
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| **触发条件** | C 文件含 `EF BF BD`(U+FFFD 替换符,表示不可逆的编码损坏) |
|
||||
| **处理方式** | **阻止提交**(不可逆,必须修复) |
|
||||
| **检测原理** | `scripts/check_mojibake.py` 以二进制读取文件,检测 `0xEF 0xBF 0xBD` 字节序列 |
|
||||
| **典型报错** | `U+FFFD replacement chars found (encoding corrupted, irreversible!): path/to/file.c` |
|
||||
| **修复方式** | 从 git 历史中找到最后一个干净版本,手动恢复损坏区域 |
|
||||
|
||||
> ⚠️ **编码铁律**:U+FFFD 是不可逆损坏(无法从替换符反推原始中文字符)。若发现新文件出现 U+FFFD,必须排查写入方式(禁用 Get-Content / Set-Content 重写中文文件)。
|
||||
|
||||
### 2.8 gitlint — Commit Message 格式
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| **触发条件** | commit message 标题超 100 字符 / 含 body-is-missing 警告 |
|
||||
| **处理方式** | **阻止提交**(commit-msg 阶段) |
|
||||
| **当前规则** | 宽松:不强制 Conventional Commits,兼容中文标题 |
|
||||
| **典型报错** | `T1 Title exceeds max length (159>100)` |
|
||||
| **修复方式** | 精简 commit message 标题到 100 字符以内,或拆分为多行(标题+空行+body) |
|
||||
|
||||
---
|
||||
|
||||
## 3. 日常工作流
|
||||
|
||||
### 3.1 正常提交(秒级完成)
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "修复网络超时重连逻辑"
|
||||
```
|
||||
|
||||
**全部钩子自动运行**,只检查本次 staged 的文件(增量扫描)。通常 <5 秒完成。
|
||||
|
||||
### 3.2 钩子失败后的处理
|
||||
|
||||
```bash
|
||||
# 提交被拦截,查看报错信息
|
||||
# 修复后重新 add + commit
|
||||
git add .
|
||||
git commit -m "修复网络超时重连逻辑"
|
||||
```
|
||||
|
||||
**常见失败场景与处理**:
|
||||
|
||||
| 钩子 | 失败表现 | 处理步骤 |
|
||||
|---|---|---|
|
||||
| trailing-whitespace | `Fixing xxx.c` → 需要重新 `git add` | 钩子已自动修复文件,`git add` 后重新提交 |
|
||||
| end-of-file-fixer | 同上 | 同上 |
|
||||
| cppcheck | 报 warning/performance/portability/style | 根据报告修复代码;误报用行内抑制或 `--suppress`(详见 `docs/cppcheck使用说明.md`)|
|
||||
| no-mojibake | `U+FFFD replacement chars found` | 从 git 历史恢复干净版本(不可逆!) |
|
||||
| gitlint | `Title exceeds max length` | 精简 commit message 标题 |
|
||||
|
||||
### 3.3 全库扫描(配置变更后)
|
||||
|
||||
```bash
|
||||
pre-commit run --all-files
|
||||
```
|
||||
|
||||
仅在以下场景使用:
|
||||
- 首次 `pre-commit install` 后确认基线
|
||||
- 修改 `.pre-commit-config.yaml` 后验证
|
||||
- `cppcheck` 新增 suppress 规则后验证
|
||||
|
||||
> 日常提交**不需要**跑 `--all-files`,pre-commit 会自动只检查 staged 文件。
|
||||
|
||||
### 3.4 手动运行单个钩子
|
||||
|
||||
```bash
|
||||
pre-commit run cppcheck --all-files # 只跑 cppcheck
|
||||
pre-commit run trailing-whitespace --files path/to/file.c # 只检查单个文件
|
||||
pre-commit run no-mojibake --files path/to/file.c
|
||||
pre-commit run gitlint --hook-stage commit-msg --commit-msg-filename .git/COMMIT_EDITMSG
|
||||
```
|
||||
|
||||
### 3.5 临时跳过钩子(紧急情况)
|
||||
|
||||
```bash
|
||||
git commit -m "紧急修复" --no-verify
|
||||
# 或跳过特定钩子
|
||||
SKIP=cppcheck git commit -m "紧急修复"
|
||||
```
|
||||
|
||||
> ⚠️ **不推荐**,仅用于紧急修复。跳过后的代码应在下一次提交中补上检查。
|
||||
|
||||
---
|
||||
|
||||
## 4. 新机器启用
|
||||
|
||||
```powershell
|
||||
# 1. 安装 pre-commit(需要 uv)
|
||||
uv tool install pre-commit
|
||||
|
||||
# 2. 安装 cppcheck(需要 winget)
|
||||
winget install cppcheck
|
||||
# 重开终端使 PATH 生效
|
||||
|
||||
# 3. 进入仓库,安装钩子
|
||||
cd D:\Code\DTU Code\STM32F4-Base
|
||||
pre-commit install
|
||||
|
||||
# 4. 首次全库扫描(确认基线)
|
||||
pre-commit run --all-files
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 已知问题与注意事项
|
||||
|
||||
### 5.1 cppcheck 找不到
|
||||
|
||||
**现象**:`Executable cppcheck not found`
|
||||
|
||||
**原因**:cppcheck 安装后 PATH 更新在注册表,已运行的终端不会刷新。
|
||||
|
||||
**解决**:重开终端即可。若需在当前会话临时修复:
|
||||
|
||||
```powershell
|
||||
$env:PATH = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Environment]::GetEnvironmentVariable("Path","User")
|
||||
```
|
||||
|
||||
### 5.4 clang-format 未启用
|
||||
|
||||
**原因**:全库 222 个 .c/.h 文件大概率不满足 clang-format 默认格式,启用后会批量重写。
|
||||
|
||||
**计划**:Route B —— 全库统一格式化后形成独立基线 commit,再启用 clang-format 钩子。启用时取消 `.pre-commit-config.yaml` 中的注释即可。
|
||||
|
||||
---
|
||||
|
||||
## 6. 文件清单
|
||||
|
||||
| 文件 | 位置 | 说明 |
|
||||
|---|---|---|
|
||||
| `.pre-commit-config.yaml` | 仓库根 | 钩子配置(7 个钩子 + 1 个预留) |
|
||||
| `.gitlint` | 仓库根 | gitlint 规则(宽松,兼容中文) |
|
||||
| `scripts/check_mojibake.py` | scripts/ | U+FFFD 检测脚本 |
|
||||
| `docs/自动化代码审查实施.md` | docs/ | 实施规划文档(Route A/B 设计) |
|
||||
| `docs/cppcheck使用说明.md` | docs/ | cppcheck 钩子详解(规则/配置/抑制) |
|
||||
| `docs/pre-commit使用说明.md` | 本文档 | 部署与使用说明 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 快速参考卡片
|
||||
|
||||
```
|
||||
提交代码: git add . && git commit -m "描述"
|
||||
全库扫描: pre-commit run --all-files
|
||||
单钩子扫描: pre-commit run <hook-id> --all-files
|
||||
扫描单个文件: pre-commit run <hook-id> --files <path>
|
||||
跳过钩子: git commit --no-verify (紧急)
|
||||
查看已安装钩子: ls .git/hooks/
|
||||
卸载钩子: pre-commit uninstall
|
||||
更新钩子版本: pre-commit autoupdate
|
||||
```
|
||||
Reference in New Issue
Block a user