@zjex/git-workflow 0.4.4 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,384 @@
1
+ # Debug 模式
2
+
3
+ Debug 模式可以帮助你诊断命令执行失败的原因,显示详细的命令、输出和错误信息。
4
+
5
+ ## 启用 Debug 模式
6
+
7
+ 在任何命令后添加 `--debug` 或 `-d` 参数:
8
+
9
+ ```bash
10
+ # 基本用法
11
+ gw tag --debug
12
+ gw tag -d
13
+
14
+ # 其他命令
15
+ gw f --debug
16
+ gw b --debug
17
+ gw c --debug
18
+ gw s --debug
19
+ ```
20
+
21
+ ## Debug 输出内容
22
+
23
+ 启用 debug 模式后,你会看到:
24
+
25
+ ### 1. 模式提示
26
+
27
+ ```
28
+ 🐛 Debug 模式已启用
29
+ ```
30
+
31
+ ### 2. 执行的命令
32
+
33
+ 每次执行 Git 命令时,会显示完整的命令字符串:
34
+
35
+ ```
36
+ [DEBUG] 执行命令: git tag -a "v1.5.3" -m "Release v1.5.3"
37
+ ```
38
+
39
+ ### 3. 退出码
40
+
41
+ 命令执行完成后显示退出码:
42
+
43
+ ```
44
+ [DEBUG] 退出码: 0
45
+ ```
46
+
47
+ - `0` 表示成功
48
+ - 非 `0` 表示失败
49
+
50
+ ### 4. 标准输出
51
+
52
+ 如果命令有标准输出,会显示:
53
+
54
+ ```
55
+ [DEBUG] 标准输出:
56
+ Counting objects: 3, done.
57
+ Writing objects: 100% (3/3), 256 bytes | 256.00 KiB/s, done.
58
+ Total 3 (delta 0), reused 0 (delta 0)
59
+ ```
60
+
61
+ ### 5. 错误输出
62
+
63
+ 如果命令失败,会显示详细的错误信息:
64
+
65
+ ```
66
+ [DEBUG] 错误输出:
67
+ fatal: Failed to resolve 'HEAD' as a valid ref.
68
+ ```
69
+
70
+ ### 6. 故障排查信息
71
+
72
+ 命令失败时,还会显示额外的排查信息:
73
+
74
+ ```
75
+ [DEBUG] 故障排查信息:
76
+ 命令: git tag -a "v1.5.3" -m "Release v1.5.3"
77
+ 工作目录: /Users/username/project
78
+ Shell: /bin/zsh
79
+ 建议: 尝试在终端中直接运行上述命令以获取更多信息
80
+ ```
81
+
82
+ ## 使用场景
83
+
84
+ ### 场景 1:Tag 创建失败
85
+
86
+ ```bash
87
+ $ gw tag --debug
88
+
89
+ 🐛 Debug 模式已启用
90
+
91
+ ✔ 选择 tag 前缀: v (最新: v1.5.2)
92
+ 当前最新 tag: v1.5.2
93
+
94
+ ────────────────────────────────────────
95
+
96
+ ✔ 选择版本类型: patch → v1.5.3
97
+
98
+ ────────────────────────────────────────
99
+
100
+ [DEBUG] 执行命令: git tag -a "v1.5.3" -m "Release v1.5.3"
101
+ [DEBUG] 退出码: 128
102
+ [DEBUG] 错误输出:
103
+ fatal: Failed to resolve 'HEAD' as a valid ref.
104
+
105
+ ✗ tag 创建失败
106
+ fatal: Failed to resolve 'HEAD' as a valid ref.
107
+
108
+ [DEBUG] 故障排查信息:
109
+ 命令: git tag -a "v1.5.3" -m "Release v1.5.3"
110
+ 工作目录: /Users/username/cmk-vue
111
+ Shell: /bin/zsh
112
+ 建议: 尝试在终端中直接运行上述命令以获取更多信息
113
+ ```
114
+
115
+ 从这个输出可以看出:
116
+
117
+ - 命令本身是正确的(引号处理正常)
118
+ - 退出码 128 表示 Git 错误
119
+ - 错误原因:`HEAD` 无法解析(仓库没有提交)
120
+
121
+ ### 场景 2:分支推送失败
122
+
123
+ ```bash
124
+ $ gw f --debug
125
+
126
+ 🐛 Debug 模式已启用
127
+
128
+ ✔ 请输入需求ID: 123
129
+ ✔ 请输入描述: add-feature
130
+
131
+ ────────────────────────────────────────
132
+
133
+ [DEBUG] 执行命令: git fetch origin main
134
+ [DEBUG] 退出码: 0
135
+
136
+ [DEBUG] 执行命令: git checkout -b "feature/20240120-123-add-feature" origin/main
137
+ [DEBUG] 退出码: 0
138
+ [DEBUG] 标准输出:
139
+ Switched to a new branch 'feature/20240120-123-add-feature'
140
+
141
+ ✔ 分支创建成功: feature/20240120-123-add-feature
142
+
143
+ ────────────────────────────────────────
144
+
145
+ (自动推送已启用)
146
+
147
+ [DEBUG] 执行命令: git push -u origin "feature/20240120-123-add-feature"
148
+ [DEBUG] 退出码: 128
149
+ [DEBUG] 错误输出:
150
+ fatal: unable to access 'https://github.com/user/repo.git/': Could not resolve host: github.com
151
+
152
+ ✗ 远程推送失败
153
+ fatal: unable to access 'https://github.com/user/repo.git/': Could not resolve host: github.com
154
+
155
+ [DEBUG] 故障排查信息:
156
+ 命令: git push -u origin "feature/20240120-123-add-feature"
157
+ 工作目录: /Users/username/project
158
+ Shell: /bin/zsh
159
+ 建议: 尝试在终端中直接运行上述命令以获取更多信息
160
+ ```
161
+
162
+ 从这个输出可以看出:
163
+
164
+ - 分支创建成功
165
+ - 推送失败是因为网络问题(无法解析 github.com)
166
+
167
+ ### 场景 3:Stash 创建失败
168
+
169
+ ```bash
170
+ $ gw s --debug
171
+
172
+ 🐛 Debug 模式已启用
173
+
174
+ 没有 stash 记录
175
+ ✔ 检测到未提交的变更,是否创建 stash? 是
176
+ ✔ Stash 消息 (可选): 临时保存:修复bug
177
+
178
+ [DEBUG] 执行命令: git stash push -m "临时保存:修复bug"
179
+ [DEBUG] 退出码: 0
180
+ [DEBUG] 标准输出:
181
+ Saved working directory and index state On master: 临时保存:修复bug
182
+
183
+ ✔ Stash 创建成功
184
+ ```
185
+
186
+ ## 对比:普通模式 vs Debug 模式
187
+
188
+ ### 普通模式
189
+
190
+ ```bash
191
+ $ gw tag
192
+
193
+ ✔ 选择 tag 前缀: v (最新: v1.5.2)
194
+ 当前最新 tag: v1.5.2
195
+
196
+ ────────────────────────────────────────
197
+
198
+ ✔ 选择版本类型: patch → v1.5.3
199
+
200
+ ────────────────────────────────────────
201
+
202
+ ✗ tag 创建失败
203
+ fatal: Failed to resolve 'HEAD' as a valid ref.
204
+ ```
205
+
206
+ ### Debug 模式
207
+
208
+ ```bash
209
+ $ gw tag --debug
210
+
211
+ 🐛 Debug 模式已启用
212
+
213
+ ✔ 选择 tag 前缀: v (最新: v1.5.2)
214
+ 当前最新 tag: v1.5.2
215
+
216
+ ────────────────────────────────────────
217
+
218
+ ✔ 选择版本类型: patch → v1.5.3
219
+
220
+ ────────────────────────────────────────
221
+
222
+ [DEBUG] 执行命令: git tag -a "v1.5.3" -m "Release v1.5.3"
223
+ [DEBUG] 退出码: 128
224
+ [DEBUG] 错误输出:
225
+ fatal: Failed to resolve 'HEAD' as a valid ref.
226
+
227
+ ✗ tag 创建失败
228
+ fatal: Failed to resolve 'HEAD' as a valid ref.
229
+
230
+ [DEBUG] 故障排查信息:
231
+ 命令: git tag -a "v1.5.3" -m "Release v1.5.3"
232
+ 工作目录: /Users/username/cmk-vue
233
+ Shell: /bin/zsh
234
+ 建议: 尝试在终端中直接运行上述命令以获取更多信息
235
+ ```
236
+
237
+ ## 常见问题排查
238
+
239
+ ### 问题 1:Failed to resolve 'HEAD'
240
+
241
+ **错误信息:**
242
+
243
+ ```
244
+ fatal: Failed to resolve 'HEAD' as a valid ref.
245
+ ```
246
+
247
+ **原因:** 仓库没有任何提交
248
+
249
+ **解决方法:**
250
+
251
+ ```bash
252
+ git add .
253
+ git commit -m "Initial commit"
254
+ gw tag
255
+ ```
256
+
257
+ ### 问题 2:Tag already exists
258
+
259
+ **错误信息:**
260
+
261
+ ```
262
+ fatal: tag 'v1.5.3' already exists
263
+ ```
264
+
265
+ **原因:** Tag 已经存在
266
+
267
+ **解决方法:**
268
+
269
+ ```bash
270
+ # 删除旧 tag
271
+ git tag -d v1.5.3
272
+ git push origin --delete v1.5.3
273
+
274
+ # 重新创建
275
+ gw tag
276
+ ```
277
+
278
+ ### 问题 3:Network error
279
+
280
+ **错误信息:**
281
+
282
+ ```
283
+ fatal: unable to access 'https://github.com/...': Could not resolve host
284
+ ```
285
+
286
+ **原因:** 网络连接问题
287
+
288
+ **解决方法:**
289
+
290
+ - 检查网络连接
291
+ - 检查代理设置
292
+ - 稍后重试
293
+
294
+ ### 问题 4:Permission denied
295
+
296
+ **错误信息:**
297
+
298
+ ```
299
+ fatal: could not read Username for 'https://github.com': terminal prompts disabled
300
+ ```
301
+
302
+ **原因:** 没有配置 Git 凭据
303
+
304
+ **解决方法:**
305
+
306
+ ```bash
307
+ # 配置 SSH
308
+ ssh-keygen -t ed25519 -C "your_email@example.com"
309
+ # 添加 SSH key 到 GitHub
310
+
311
+ # 或使用 HTTPS + token
312
+ git config --global credential.helper store
313
+ ```
314
+
315
+ ## 提交 Bug 报告
316
+
317
+ 如果你遇到问题需要提交 bug 报告,请:
318
+
319
+ 1. **使用 debug 模式重现问题**
320
+
321
+ ```bash
322
+ gw <command> --debug > debug.log 2>&1
323
+ ```
324
+
325
+ 2. **包含以下信息**
326
+ - 完整的 debug 输出
327
+ - 操作系统和 Shell 版本
328
+ - Git 版本:`git --version`
329
+ - gw 版本:`gw --version`
330
+ - 仓库状态:`git status`
331
+
332
+ 3. **提交到 GitHub Issues**
333
+ - 附上 `debug.log` 文件
334
+ - 描述期望的行为
335
+ - 描述实际的行为
336
+
337
+ ## 性能影响
338
+
339
+ Debug 模式会:
340
+
341
+ - ✅ 捕获额外的输出信息
342
+ - ✅ 显示更多日志
343
+ - ⚠️ 轻微增加执行时间(通常 < 100ms)
344
+ - ✅ 不影响命令的实际功能
345
+
346
+ 建议:
347
+
348
+ - 日常使用:不启用 debug 模式
349
+ - 遇到问题:启用 debug 模式排查
350
+ - 提交 bug:必须提供 debug 输出
351
+
352
+ ## 相关命令
353
+
354
+ ```bash
355
+ # 查看版本
356
+ gw --version
357
+ gw -v
358
+
359
+ # 查看帮助
360
+ gw --help
361
+ gw -h
362
+
363
+ # 启用 debug
364
+ gw <command> --debug
365
+ gw <command> -d
366
+
367
+ # 组合使用(不支持)
368
+ # ❌ gw --version --debug # 不会显示 debug 信息
369
+ # ✅ gw tag --debug # 正确用法
370
+ ```
371
+
372
+ ## 实现细节
373
+
374
+ Debug 模式通过以下方式实现:
375
+
376
+ 1. **全局标志**:在主入口设置全局 `DEBUG_MODE` 标志
377
+ 2. **命令拦截**:在 `execAsync` 中检查 debug 模式
378
+ 3. **输出捕获**:捕获 stdout 和 stderr
379
+ 4. **格式化输出**:使用颜色和前缀标识 debug 信息
380
+
381
+ 相关文件:
382
+
383
+ - `src/index.ts` - 解析 `--debug` 参数
384
+ - `src/utils.ts` - 实现 debug 输出逻辑
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zjex/git-workflow",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "🚀 极简的 Git 工作流 CLI 工具,让分支管理和版本发布变得轻松愉快",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,14 +19,33 @@ function formatGitDate(date: Date): string {
19
19
 
20
20
  /**
21
21
  * 解析用户输入的日期
22
- * 支持格式:YYYY-MM-DD (默认 00:00:00)
22
+ * 支持格式:
23
+ * - YYYY-MM-DD (默认 00:00:00)
24
+ * - YYYY-MM-DD HH:mm:ss
23
25
  * @param input 用户输入
24
26
  * @returns Date 对象或 null
25
27
  */
26
28
  function parseDate(input: string): Date | null {
27
29
  const trimmed = input.trim();
28
- const dateMatch = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})$/);
29
30
 
31
+ // 尝试匹配完整格式: YYYY-MM-DD HH:mm:ss
32
+ const fullMatch = trimmed.match(
33
+ /^(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})$/,
34
+ );
35
+ if (fullMatch) {
36
+ const [, year, month, day, hours, minutes, seconds] = fullMatch;
37
+ return new Date(
38
+ parseInt(year),
39
+ parseInt(month) - 1,
40
+ parseInt(day),
41
+ parseInt(hours),
42
+ parseInt(minutes),
43
+ parseInt(seconds),
44
+ );
45
+ }
46
+
47
+ // 尝试匹配简化格式: YYYY-MM-DD (默认 00:00:00)
48
+ const dateMatch = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})$/);
30
49
  if (dateMatch) {
31
50
  const [, year, month, day] = dateMatch;
32
51
  return new Date(
@@ -120,7 +139,6 @@ export async function amendDate(commitHash?: string): Promise<void> {
120
139
  value: c,
121
140
  description: c.date,
122
141
  })),
123
- pageSize: 15,
124
142
  theme,
125
143
  });
126
144
  }
@@ -133,7 +151,9 @@ export async function amendDate(commitHash?: string): Promise<void> {
133
151
  divider();
134
152
 
135
153
  // ========== 步骤 2: 输入新日期 ==========
136
- console.log(colors.dim("输入日期格式: YYYY-MM-DD (如: 2026-01-19)"));
154
+ console.log(colors.dim("支持格式:"));
155
+ console.log(colors.dim(" YYYY-MM-DD (如: 2026-01-19,默认 00:00:00)"));
156
+ console.log(colors.dim(" YYYY-MM-DD HH:mm:ss (如: 2026-01-19 14:30:00)"));
137
157
  console.log("");
138
158
 
139
159
  const dateInput = await input({
@@ -141,7 +161,7 @@ export async function amendDate(commitHash?: string): Promise<void> {
141
161
  validate: (value) => {
142
162
  const parsed = parseDate(value);
143
163
  if (!parsed) {
144
- return "日期格式不正确,请使用 YYYY-MM-DD 格式";
164
+ return "日期格式不正确,请使用 YYYY-MM-DD 或 YYYY-MM-DD HH:mm:ss 格式";
145
165
  }
146
166
  return true;
147
167
  },
@@ -79,7 +79,6 @@ export async function amend(commitHash?: string): Promise<void> {
79
79
  value: c,
80
80
  description: c.message,
81
81
  })),
82
- pageSize: 15,
83
82
  theme,
84
83
  });
85
84
  }
package/src/index.ts CHANGED
@@ -13,7 +13,7 @@
13
13
  import { cac } from "cac";
14
14
  import { select } from "@inquirer/prompts";
15
15
  import { ExitPromptError } from "@inquirer/core";
16
- import { checkGitRepo, theme, colors } from "./utils.js";
16
+ import { checkGitRepo, theme, colors, setDebugMode } from "./utils.js";
17
17
  import { createBranch, deleteBranch } from "./commands/branch.js";
18
18
  import {
19
19
  listTags,
@@ -488,12 +488,20 @@ cli
488
488
  console.log("");
489
489
  });
490
490
 
491
- // 不使用 cac 的 version,手动处理 --version 和 --help
491
+ // 不使用 cac 的 version,手动处理 --version、--help 和 --debug
492
492
  cli.option("-v, --version", "显示版本号");
493
493
  cli.option("-h, --help", "显示帮助信息");
494
+ cli.option("-d, --debug", "启用调试模式,显示详细的命令和错误信息");
494
495
 
495
- // 在 parse 之前检查 --version 和 --help
496
+ // 在 parse 之前检查 --version、--help 和 --debug
496
497
  const processArgs = process.argv.slice(2);
498
+
499
+ // 检查是否启用 debug 模式
500
+ if (processArgs.includes("-d") || processArgs.includes("--debug")) {
501
+ setDebugMode(true);
502
+ console.log(colors.yellow("🐛 Debug 模式已启用\n"));
503
+ }
504
+
497
505
  if (processArgs.includes("-v") || processArgs.includes("--version")) {
498
506
  console.log(colors.yellow(`v${version}`));
499
507
  process.exit(0);
package/src/utils.ts CHANGED
@@ -1,6 +1,25 @@
1
1
  import { execSync, spawn, type ExecSyncOptions } from "child_process";
2
2
  import type { Ora } from "ora";
3
3
 
4
+ /**
5
+ * 全局 debug 模式标志
6
+ */
7
+ let debugMode = false;
8
+
9
+ /**
10
+ * 设置 debug 模式(由主入口调用)
11
+ */
12
+ export function setDebugMode(enabled: boolean): void {
13
+ debugMode = enabled;
14
+ }
15
+
16
+ /**
17
+ * 获取当前 debug 模式状态
18
+ */
19
+ export function isDebugMode(): boolean {
20
+ return debugMode;
21
+ }
22
+
4
23
  export interface Colors {
5
24
  red: (s: string) => string;
6
25
  green: (s: string) => string;
@@ -104,22 +123,68 @@ export function divider(): void {
104
123
  * 使用 spawn 异步执行命令,避免阻塞 spinner
105
124
  * @param command 命令字符串
106
125
  * @param spinner 可选的 ora spinner 实例
107
- * @returns Promise<boolean> 成功返回 true,失败返回 false
126
+ * @returns Promise<{success: boolean, error?: string}> 返回执行结果和错误信息
108
127
  */
109
- export function execAsync(command: string, spinner?: Ora): Promise<boolean> {
128
+ export function execAsync(
129
+ command: string,
130
+ spinner?: Ora,
131
+ ): Promise<{ success: boolean; error?: string }> {
110
132
  return new Promise((resolve) => {
111
- const [cmd, ...args] = command.split(" ");
133
+ // Debug 模式:显示执行的命令
134
+ if (debugMode) {
135
+ console.log(colors.dim(`\n[DEBUG] 执行命令: ${colors.cyan(command)}`));
136
+ }
112
137
 
113
- const process = spawn(cmd, args, {
138
+ // 使用 shell 模式执行命令,这样可以正确处理引号
139
+ const process = spawn(command, {
114
140
  stdio: spinner ? "pipe" : "inherit",
141
+ shell: true,
115
142
  });
116
143
 
144
+ let errorOutput = "";
145
+ let stdoutOutput = "";
146
+
147
+ // 捕获标准输出(debug 模式)
148
+ if (debugMode && process.stdout) {
149
+ process.stdout.on("data", (data) => {
150
+ stdoutOutput += data.toString();
151
+ });
152
+ }
153
+
154
+ // 捕获错误输出
155
+ if (process.stderr) {
156
+ process.stderr.on("data", (data) => {
157
+ errorOutput += data.toString();
158
+ });
159
+ }
160
+
117
161
  process.on("close", (code) => {
118
- resolve(code === 0);
162
+ // Debug 模式:显示退出码和输出
163
+ if (debugMode) {
164
+ console.log(colors.dim(`[DEBUG] 退出码: ${code}`));
165
+ if (stdoutOutput) {
166
+ console.log(colors.dim(`[DEBUG] 标准输出:\n${stdoutOutput}`));
167
+ }
168
+ if (errorOutput) {
169
+ console.log(colors.dim(`[DEBUG] 错误输出:\n${errorOutput}`));
170
+ }
171
+ }
172
+
173
+ if (code === 0) {
174
+ resolve({ success: true });
175
+ } else {
176
+ resolve({ success: false, error: errorOutput.trim() });
177
+ }
119
178
  });
120
179
 
121
- process.on("error", () => {
122
- resolve(false);
180
+ process.on("error", (err) => {
181
+ // Debug 模式:显示进程错误
182
+ if (debugMode) {
183
+ console.log(colors.dim(`[DEBUG] 进程错误: ${err.message}`));
184
+ console.log(colors.dim(`[DEBUG] 错误堆栈:\n${err.stack}`));
185
+ }
186
+
187
+ resolve({ success: false, error: err.message });
123
188
  });
124
189
  });
125
190
  }
@@ -138,9 +203,9 @@ export async function execWithSpinner(
138
203
  successMessage?: string,
139
204
  errorMessage?: string,
140
205
  ): Promise<boolean> {
141
- const success = await execAsync(command, spinner);
206
+ const result = await execAsync(command, spinner);
142
207
 
143
- if (success) {
208
+ if (result.success) {
144
209
  if (successMessage) {
145
210
  spinner.succeed(successMessage);
146
211
  } else {
@@ -152,7 +217,23 @@ export async function execWithSpinner(
152
217
  } else {
153
218
  spinner.fail();
154
219
  }
220
+
221
+ // 显示具体的错误信息
222
+ if (result.error) {
223
+ console.log(colors.dim(` ${result.error}`));
224
+ }
225
+
226
+ // Debug 模式:显示完整的命令和建议
227
+ if (debugMode) {
228
+ console.log(colors.yellow("\n[DEBUG] 故障排查信息:"));
229
+ console.log(colors.dim(` 命令: ${command}`));
230
+ console.log(colors.dim(` 工作目录: ${process.cwd()}`));
231
+ console.log(colors.dim(` Shell: ${process.env.SHELL || "unknown"}`));
232
+ console.log(
233
+ colors.dim(` 建议: 尝试在终端中直接运行上述命令以获取更多信息\n`),
234
+ );
235
+ }
155
236
  }
156
237
 
157
- return success;
238
+ return result.success;
158
239
  }