git-yike-logger-hook
v1.0.0
Published
A TypeScript Git hook plugin for automatically generating commit logs with TODO/WIP comment scanning
Downloads
3
Maintainers
Readme
Git Logger Hook
一个用 TypeScript 编写的 Git hook 插件,用于在每次 commit 时自动生成详细的提交日志,并扫描代码中的 TODO 和 WIP 注释。
📋 目录
功能特性
- 🔍 自动记录提交信息:记录提交人、提交时间、提交消息和提交哈希
- 📁 文件变更跟踪:详细记录新增、修改、删除和重命名的文件
- 🌿 分支信息:记录当前分支和远程仓库信息
- 💬 代码注释扫描:自动扫描 JavaScript/TypeScript 文件中的 TODO 和 WIP 注释
- 📊 JSON 格式:结构化的 JSON 日志,便于后续处理和分析
- 🧹 自动清理:可配置保留最近 N 个日志文件
- ⚙️ 易于配置:支持自定义日志目录和文件过滤
- 🚀 零配置启动:安装后即可使用,无需额外配置
开发思路
核心设计理念
- 自动化优先:通过 Git hook 机制实现完全自动化的日志记录
- 最小侵入性:不影响现有开发流程,透明地记录信息
- 结构化数据:使用 JSON 格式便于后续分析和处理
- 可扩展性:模块化设计,易于添加新功能
技术选型理由
- TypeScript:提供类型安全,减少运行时错误
- simple-git:简化 Git 操作,避免直接调用 Git 命令
- Node.js:跨平台支持,与 Git 生态良好集成
- Git Hooks:利用 Git 原生机制,无需额外工具
工作流程
graph TD
A[开发者执行 git commit] --> B[触发 pre-commit hook]
B --> C[GitLogger 开始工作]
C --> D[获取提交信息]
D --> E[获取文件变更]
E --> F[扫描代码注释]
F --> G[生成 JSON 日志]
G --> H[保存到 .git-logs 目录]
H --> I[提交继续执行]技术架构
整体架构图
graph TB
subgraph "Git Hook 层"
A[pre-commit hook] --> B[hook.ts]
end
subgraph "核心模块"
B --> C[GitLogger]
C --> D[GitUtils]
C --> E[CommentScanner]
end
subgraph "数据层"
D --> F[Git 仓库]
E --> G[JavaScript/TypeScript 文件]
C --> H[JSON 日志文件]
end
subgraph "类型系统"
I[types.ts] --> C
I --> D
I --> E
end模块依赖关系
hook.ts→GitLogger→GitUtils+CommentScanner- 所有模块都依赖
types.ts进行类型定义 install.ts独立运行,负责 Git hook 的安装和卸载
依赖说明
核心依赖
| 依赖 | 版本 | 作用 | 选择理由 |
|------|------|------|----------|
| simple-git | ^3.19.0 | Git 操作封装 | 简化 Git 命令调用,提供 Promise 接口 |
| @types/node | ^20.0.0 | Node.js 类型定义 | 提供 Node.js API 的类型支持 |
| typescript | ^5.0.0 | TypeScript 编译器 | 编译 TypeScript 代码 |
依赖作用详解
simple-git
// 示例:获取提交信息
const git = simpleGit();
const log = await git.log({ maxCount: 1 });
const commit = log.latest;为什么选择 simple-git?
- 提供统一的 Promise 接口
- 自动处理 Git 命令的复杂参数
- 内置错误处理和重试机制
- 支持所有主流 Git 操作
TypeScript
- 提供编译时类型检查
- 增强代码可读性和维护性
- 提供智能代码补全和重构支持
模块详解
核心模块
1. types.ts - 类型定义模块
// 核心数据结构定义
export interface CommitLog { ... }
export interface CodeComment { ... }
export interface GitStatus { ... }
export interface LoggerConfig { ... }作用:
- 定义所有模块使用的数据结构
- 提供类型安全保障
- 作为模块间的契约
关键点:
- 使用接口而非类型别名,便于扩展
- 所有字段都有明确的注释说明
- 支持可选字段,增强灵活性
2. git-utils.ts - Git 操作工具类
export class GitUtils {
async getCurrentCommitInfo(): Promise<Partial<CommitLog>>
async getCurrentBranch(): Promise<string>
async getRemoteInfo(): Promise<{ name: string; url: string } | undefined>
async getFileChanges(): Promise<{ added: string[]; modified: string[]; ... }>
}作用:
- 封装所有 Git 相关操作
- 提供统一的错误处理
- 处理首次提交等边界情况
关键点:
- 使用 simple-git 简化 Git 操作
- 完善的错误处理和降级策略
- 支持首次提交的特殊处理
3. comment-scanner.ts - 代码注释扫描器
export class CommentScanner {
async scanDirectory(dirPath: string): Promise<{ todos: CodeComment[]; wips: CodeComment[] }>
async scanFile(filePath: string): Promise<{ todos: CodeComment[]; wips: CodeComment[] }>
async scanChangedFiles(changedFiles: {...}): Promise<{ todos: CodeComment[]; wips: CodeComment[] }>
}作用:
- 扫描 JavaScript/TypeScript 文件中的注释
- 支持多种注释格式(单行、多行、@todo、@wip 等)
- 智能过滤文件类型和目录
关键点:
- 使用正则表达式匹配注释模式
- 支持多种文件扩展名
- 自动跳过 node_modules 等目录
- 提供精确的行号和文件路径信息
4. logger.ts - 日志生成器(核心模块)
export class GitLogger {
constructor(config: Partial<LoggerConfig> = {})
async generateLog(): Promise<void>
async getAllLogs(): Promise<CommitLog[]>
async cleanupLogs(keepCount: number): Promise<void>
}作用:
- 协调各个模块完成日志生成
- 管理日志文件的存储和清理
- 提供统一的配置接口
关键点:
- 组合模式:协调 GitUtils 和 CommentScanner
- 异步处理:所有操作都是异步的
- 错误处理:完善的错误处理和用户提示
- 文件管理:自动创建目录和清理旧文件
5. hook.ts - Git Hook 入口点
#!/usr/bin/env node
async function main() {
const logger = new GitLogger();
await logger.generateLog();
await logger.cleanupLogs(100);
}作用:
- 作为 Git hook 的入口点
- 处理命令行参数
- 提供用户友好的输出
关键点:
- 使用 shebang 支持直接执行
- 完善的错误处理和退出码
- 清晰的用户反馈
6. install.ts - Hook 安装器
export class HookInstaller {
async install(): Promise<void>
async uninstall(): Promise<void>
private createPreCommitHook(): void
private createPostCommitHook(): void
}作用:
- 自动安装和卸载 Git hooks
- 生成跨平台的 hook 脚本
- 验证 Git 仓库环境
关键点:
- 跨平台支持(Windows/Unix)
- 自动检测 Git 仓库
- 生成可执行的 hook 脚本
辅助模块
index.ts - 模块导出
export { GitLogger } from './logger';
export { GitUtils } from './git-utils';
export { CommentScanner } from './comment-scanner';
export { CommitLog, GitStatus, LoggerConfig, CodeComment } from './types';作用:
- 提供统一的模块导出接口
- 简化外部使用
- 支持默认导出
快速开始
1. 安装依赖
npm install2. 编译项目
npm run build3. 安装 Git Hook
npm run install-hook4. 开始使用
现在每次执行 git commit 时,插件会自动在 .git-logs 目录中生成一个 JSON 日志文件。
日志格式
生成的日志文件格式如下:
{
"author": {
"name": "用户名",
"email": "[email protected]"
},
"timestamp": "2024-01-01T12:00:00.000Z",
"message": "提交信息",
"commitHash": "abc123def456...",
"changedFiles": {
"added": ["新文件1.js", "新文件2.ts"],
"modified": ["修改的文件.js"],
"deleted": ["删除的文件.js"],
"renamed": [
{
"from": "旧文件名.js",
"to": "新文件名.js"
}
]
},
"branch": "main",
"remote": {
"name": "origin",
"url": "https://github.com/user/repo.git"
},
"comments": {
"todos": [
{
"type": "TODO",
"content": "实现这个功能",
"filePath": "src/example.js",
"lineNumber": 10,
"fullLine": "// TODO: 实现这个功能"
}
],
"wips": [
{
"type": "WIP",
"content": "这个功能还在开发中",
"filePath": "src/example.js",
"lineNumber": 15,
"fullLine": "// WIP: 这个功能还在开发中"
}
]
}
}配置选项
可以通过修改 src/logger.ts 中的配置来自定义行为:
const logger = new GitLogger({
logDir: '.git-logs', // 日志文件保存目录
includeUnstaged: false, // 是否包含未暂存的更改
includeUntracked: false, // 是否包含未跟踪的文件
filePatterns: ['*.js', '*.ts'], // 文件过滤模式(可选)
});可用脚本
npm run build- 编译 TypeScript 代码npm run dev- 监听模式编译npm run install-hook- 安装 Git hooknode dist/install.js uninstall- 卸载 Git hook
项目结构
src/
├── index.ts # 主入口文件
├── types.ts # TypeScript 类型定义
├── git-utils.ts # Git 操作工具类
├── comment-scanner.ts # 代码注释扫描器
├── logger.ts # 日志生成器
├── hook.ts # Git hook 入口点
└── install.ts # Hook 安装器日志文件命名
日志文件按以下格式命名:
YYYY-MM-DD_HH-MM-SS_<commit-hash>.json例如:2024-01-01_12-30-45_abc12345.json
自动清理
插件会自动保留最近的 100 个日志文件,超出部分会被自动删除。可以通过修改 logger.ts 中的 cleanupLogs(100) 来调整保留数量。
卸载
如果需要卸载 Git hook:
node dist/install.js uninstallAPI 文档
GitLogger 类
构造函数
constructor(config?: Partial<LoggerConfig>)参数:
config(可选): 配置选项,支持以下属性:logDir: 日志文件保存目录,默认.git-logsincludeUnstaged: 是否包含未暂存的更改,默认falseincludeUntracked: 是否包含未跟踪的文件,默认falsefilePatterns: 文件过滤模式,默认undefined
方法
generateLog()
async generateLog(): Promise<void>生成并保存当前提交的日志。
返回值: Promise<void>
异常:
- 如果不在 Git 仓库中,抛出错误
- 如果无法获取提交信息,抛出错误
getAllLogs()
async getAllLogs(): Promise<CommitLog[]>获取所有日志文件。
返回值: Promise<CommitLog[]> - 按时间倒序排列的日志数组
cleanupLogs()
async cleanupLogs(keepCount: number): Promise<void>清理旧日志文件。
参数:
keepCount: 保留的日志文件数量
返回值: Promise<void>
GitUtils 类
方法
getCurrentCommitInfo()
async getCurrentCommitInfo(): Promise<Partial<CommitLog>>获取当前提交信息。
返回值: Promise<Partial<CommitLog>> - 包含提交人、时间、消息、哈希等信息
getCurrentBranch()
async getCurrentBranch(): Promise<string>获取当前分支名称。
返回值: Promise<string> - 分支名称,如果无法获取则返回 'unknown'
getFileChanges()
async getFileChanges(): Promise<{
added: string[];
modified: string[];
deleted: string[];
renamed: Array<{ from: string; to: string }>;
}>获取文件变更信息。
返回值: 包含新增、修改、删除、重命名文件的对象
CommentScanner 类
方法
scanDirectory()
async scanDirectory(dirPath: string): Promise<{
todos: CodeComment[];
wips: CodeComment[];
}>扫描目录下所有 JavaScript/TypeScript 文件。
参数:
dirPath: 要扫描的目录路径
返回值: 包含 TODO 和 WIP 注释的对象
scanFile()
async scanFile(filePath: string): Promise<{
todos: CodeComment[];
wips: CodeComment[];
}>扫描单个文件。
参数:
filePath: 文件路径
返回值: 包含 TODO 和 WIP 注释的对象
scanChangedFiles()
async scanChangedFiles(changedFiles: {
added: string[];
modified: string[];
deleted: string[];
}): Promise<{
todos: CodeComment[];
wips: CodeComment[];
}>扫描变更的文件。
参数:
changedFiles: 变更文件列表
返回值: 包含 TODO 和 WIP 注释的对象
开发指南
环境要求
- Node.js >= 16.0.0
- Git >= 2.0.0
- TypeScript >= 5.0.0
开发环境设置
- 克隆项目
git clone <repository-url>
cd git-logger-hook- 安装依赖
npm install- 编译项目
npm run build- 开发模式
npm run dev # 监听模式编译添加新功能
1. 添加新的注释类型
在 src/comment-scanner.ts 中添加新的正则表达式模式:
private newCommentPatterns = [
/\/\/\s*FIXME\s*:?\s*(.+)/gi,
/\/\*\s*FIXME\s*:?\s*(.+?)\s*\*\//gi
];2. 扩展日志数据结构
在 src/types.ts 中添加新的字段:
export interface CommitLog {
// ... 现有字段
newField?: string; // 新字段
}3. 添加新的 Git 操作
在 src/git-utils.ts 中添加新方法:
async getNewGitInfo(): Promise<any> {
// 实现新的 Git 操作
}测试
单元测试
# 运行测试(需要先配置测试框架)
npm test集成测试
# 创建测试提交
git add .
git commit -m "测试提交"手动测试
# 直接运行 hook
node dist/hook.js调试
启用详细日志
// 在 logger.ts 中添加
console.log('调试信息:', data);检查 Git Hook
# 查看 pre-commit hook 内容
cat .git/hooks/pre-commit检查日志文件
# 查看最新日志
ls -la .git-logs/
cat .git-logs/最新日志文件.json性能优化
1. 文件扫描优化
- 只扫描变更的文件,不扫描整个项目
- 使用文件扩展名过滤,减少不必要的文件读取
- 跳过 node_modules 等大型目录
2. 内存优化
- 及时清理旧日志文件
- 使用流式处理大文件
- 避免在内存中保存大量数据
3. 错误处理
- 提供降级策略
- 记录详细的错误信息
- 避免因单个文件错误导致整个流程失败
故障排除
常见问题
1. Hook 不执行
症状: 提交时没有生成日志文件
解决方案:
# 检查 hook 是否存在
ls -la .git/hooks/pre-commit
# 重新安装 hook
node dist/install.js install
# 检查 hook 权限(Unix 系统)
chmod +x .git/hooks/pre-commit2. 编译错误
症状: npm run build 失败
解决方案:
# 清理并重新安装依赖
rm -rf node_modules package-lock.json
npm install
# 检查 TypeScript 配置
npx tsc --noEmit3. 权限错误
症状: 无法写入日志文件
解决方案:
# 检查目录权限
ls -la .git-logs/
# 创建目录
mkdir -p .git-logs
chmod 755 .git-logs4. Git 操作失败
症状: 无法获取 Git 信息
解决方案:
# 检查是否在 Git 仓库中
git status
# 检查 Git 配置
git config --list调试技巧
1. 启用详细输出
// 在代码中添加调试信息
console.log('当前目录:', process.cwd());
console.log('Git 状态:', await git.status());2. 检查环境变量
# 检查 Node.js 版本
node --version
# 检查 Git 版本
git --version
# 检查环境变量
echo $PATH3. 查看错误日志
# 查看 Git hook 错误
git commit -m "测试" 2>&1 | tee error.log注释扫描功能
插件会自动扫描变更的 JavaScript/TypeScript 文件,提取以下类型的注释:
支持的注释格式
TODO 注释:
// TODO: 描述内容/* TODO: 描述内容 */// @todo: 描述内容/* @todo: 描述内容 */
WIP 注释:
// WIP: 描述内容/* WIP: 描述内容 */// @wip: 描述内容/* @wip: 描述内容 */// WORK IN PROGRESS: 描述内容/* WORK IN PROGRESS: 描述内容 */
支持的文件类型
.js- JavaScript 文件.jsx- React JSX 文件.ts- TypeScript 文件.tsx- React TypeScript 文件.vue- Vue 单文件组件.svelte- Svelte 组件
注释信息结构
每个提取的注释包含:
type: 注释类型(TODO 或 WIP)content: 注释内容filePath: 文件路径lineNumber: 行号fullLine: 完整的注释行
注意事项
- 确保在 Git 仓库根目录中运行安装命令
- 需要先编译项目才能使用 hook
- 在 Windows 系统上,hook 文件会同时创建
.sh和.cmd版本 - 日志文件默认保存在
.git-logs目录中,该目录已被添加到.gitignore - 注释扫描只针对变更的文件,不会扫描整个项目
许可证
MIT License
