@zjex/git-workflow 0.4.1 → 0.4.3
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.
- package/CHANGELOG.md +29 -0
- package/README.md +1 -8
- package/dist/index.js +323 -11
- package/docs/.vitepress/config.ts +2 -0
- package/docs/commands/amend-date.md +425 -0
- package/docs/commands/amend.md +380 -0
- package/docs/commands/index.md +14 -10
- package/package.json +1 -1
- package/src/commands/amend-date.ts +228 -0
- package/src/commands/amend.ts +189 -0
- package/src/index.ts +39 -4
- package/tests/amend-date.test.ts +364 -0
- package/tests/amend.test.ts +441 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v0.4.2](https://github.com/iamzjt-front-end/git-workflow/compare/v0.4.1...v0.4.2) (2026-01-19)
|
|
4
|
+
|
|
5
|
+
### 📖 Documentation
|
|
6
|
+
|
|
7
|
+
- 移除冗余的快速链接部分 ([330b323](https://github.com/iamzjt-front-end/git-workflow/commit/330b323))
|
|
8
|
+
|
|
9
|
+
### 🔧 Chore
|
|
10
|
+
|
|
11
|
+
- 🔖 chore(release): 发布 v0.4.2 ([5d59590](https://github.com/iamzjt-front-end/git-workflow/commit/5d59590))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [v0.4.1](https://github.com/iamzjt-front-end/git-workflow/compare/v0.4.0...v0.4.1) (2026-01-16)
|
|
15
|
+
|
|
16
|
+
### ✨ Features
|
|
17
|
+
|
|
18
|
+
- 更新文档内容和链接格式 ([31bd691](https://github.com/iamzjt-front-end/git-workflow/commit/31bd691))
|
|
19
|
+
|
|
20
|
+
### 📖 Documentation
|
|
21
|
+
|
|
22
|
+
- 更新文档中的链接为绝对路径 ([842cbdb](https://github.com/iamzjt-front-end/git-workflow/commit/842cbdb))
|
|
23
|
+
- 📝 docs: 自动更新测试数量徽章 [skip ci] ([c234272](https://github.com/iamzjt-front-end/git-workflow/commit/c234272))
|
|
24
|
+
|
|
25
|
+
### 🔧 Chore
|
|
26
|
+
|
|
27
|
+
- 🔖 chore(release): 发布 v0.4.1 ([83d9263](https://github.com/iamzjt-front-end/git-workflow/commit/83d9263))
|
|
28
|
+
- 添加变更日志文件并更新版本信息 ([4d06a46](https://github.com/iamzjt-front-end/git-workflow/commit/4d06a46))
|
|
29
|
+
- 🔧 chore(docs): 删除过时的文档文件和更新说明 ([e1974a2](https://github.com/iamzjt-front-end/git-workflow/commit/e1974a2))
|
|
30
|
+
|
|
31
|
+
|
|
3
32
|
## [v0.4.0](https://github.com/iamzjt-front-end/git-workflow/compare/v0.3.10...v0.4.0) (2026-01-15)
|
|
4
33
|
|
|
5
34
|
### 📖 Documentation
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<a href="https://github.com/iamzjt-front-end/git-workflow"><img src="https://img.shields.io/github/stars/iamzjt-front-end/git-workflow?style=flat&colorA=18181B&colorB=F59E0B" alt="github stars"></a>
|
|
13
13
|
<a href="https://github.com/iamzjt-front-end/git-workflow/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@zjex/git-workflow?style=flat&colorA=18181B&colorB=10B981" alt="license"></a>
|
|
14
14
|
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E%3D18-339933?style=flat&logo=node.js&logoColor=white&colorA=18181B" alt="node version"></a>
|
|
15
|
-
<a href="https://github.com/iamzjt-front-end/git-workflow/actions"><img src="https://img.shields.io/badge/tests-
|
|
15
|
+
<a href="https://github.com/iamzjt-front-end/git-workflow/actions"><img src="https://img.shields.io/badge/tests-431%20passed-success?style=flat&colorA=18181B" alt="tests"></a>
|
|
16
16
|
<a href="https://github.com/iamzjt-front-end/git-workflow/issues"><img src="https://img.shields.io/github/issues/iamzjt-front-end/git-workflow?style=flat&colorA=18181B&colorB=EC4899" alt="issues"></a>
|
|
17
17
|
</p>
|
|
18
18
|
|
|
@@ -20,13 +20,6 @@
|
|
|
20
20
|
<strong>🚀 极简的 Git 工作流 CLI 工具,让分支管理和版本发布变得轻松愉快</strong>
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
|
-
<p align="center">
|
|
24
|
-
<a href="#⚡️-快速开始">快速开始</a> •
|
|
25
|
-
<a href="#✨-核心特性">核心特性</a> •
|
|
26
|
-
<a href="#📚-完整文档">完整文档</a> •
|
|
27
|
-
<a href="#🤝-贡献">贡献</a>
|
|
28
|
-
</p>
|
|
29
|
-
|
|
30
23
|
<p align="center">
|
|
31
24
|
<strong>📚 <a href="https://iamzjt-front-end.github.io/git-workflow/">完整文档</a> | 🚀 <a href="https://iamzjt-front-end.github.io/git-workflow/guide/getting-started">快速开始</a> | 📖 <a href="https://iamzjt-front-end.github.io/git-workflow/commands/">命令参考</a> | ⚙️ <a href="https://iamzjt-front-end.github.io/git-workflow/config/">配置指南</a></strong>
|
|
32
25
|
</p>
|
package/dist/index.js
CHANGED
|
@@ -322,7 +322,7 @@ var init_update_notifier = __esm({
|
|
|
322
322
|
// src/index.ts
|
|
323
323
|
init_utils();
|
|
324
324
|
import { cac } from "cac";
|
|
325
|
-
import { select as
|
|
325
|
+
import { select as select10 } from "@inquirer/prompts";
|
|
326
326
|
import { ExitPromptError } from "@inquirer/core";
|
|
327
327
|
|
|
328
328
|
// src/commands/branch.ts
|
|
@@ -573,7 +573,7 @@ async function deleteBranch(branchArg) {
|
|
|
573
573
|
}
|
|
574
574
|
if (branch.startsWith("__remote__")) {
|
|
575
575
|
const remoteBranch = branch.replace("__remote__", "");
|
|
576
|
-
const
|
|
576
|
+
const confirm3 = await select({
|
|
577
577
|
message: `\u786E\u8BA4\u5220\u9664\u8FDC\u7A0B\u5206\u652F origin/${remoteBranch}?`,
|
|
578
578
|
choices: [
|
|
579
579
|
{ name: "\u662F", value: true },
|
|
@@ -581,7 +581,7 @@ async function deleteBranch(branchArg) {
|
|
|
581
581
|
],
|
|
582
582
|
theme
|
|
583
583
|
});
|
|
584
|
-
if (!
|
|
584
|
+
if (!confirm3) {
|
|
585
585
|
console.log(colors.yellow("\u5DF2\u53D6\u6D88"));
|
|
586
586
|
return;
|
|
587
587
|
}
|
|
@@ -1015,7 +1015,7 @@ async function deleteTag() {
|
|
|
1015
1015
|
console.log(colors.yellow("\u5DF2\u53D6\u6D88"));
|
|
1016
1016
|
return;
|
|
1017
1017
|
}
|
|
1018
|
-
const
|
|
1018
|
+
const confirm3 = await select2({
|
|
1019
1019
|
message: `\u786E\u8BA4\u5220\u9664 tag: ${colors.red(tagToDelete)}?`,
|
|
1020
1020
|
choices: [
|
|
1021
1021
|
{ name: "\u662F", value: true },
|
|
@@ -1023,7 +1023,7 @@ async function deleteTag() {
|
|
|
1023
1023
|
],
|
|
1024
1024
|
theme
|
|
1025
1025
|
});
|
|
1026
|
-
if (!
|
|
1026
|
+
if (!confirm3) {
|
|
1027
1027
|
console.log(colors.yellow("\u5DF2\u53D6\u6D88"));
|
|
1028
1028
|
return;
|
|
1029
1029
|
}
|
|
@@ -3118,6 +3118,292 @@ async function log(options = {}) {
|
|
|
3118
3118
|
executeTimelineLog(options);
|
|
3119
3119
|
}
|
|
3120
3120
|
|
|
3121
|
+
// src/commands/amend-date.ts
|
|
3122
|
+
init_utils();
|
|
3123
|
+
import { execSync as execSync9 } from "child_process";
|
|
3124
|
+
import { select as select8, input as input6, confirm } from "@inquirer/prompts";
|
|
3125
|
+
function formatGitDate(date) {
|
|
3126
|
+
const year = date.getFullYear();
|
|
3127
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
3128
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
3129
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
3130
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
3131
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
3132
|
+
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
3133
|
+
}
|
|
3134
|
+
function parseDate(input8) {
|
|
3135
|
+
const trimmed = input8.trim();
|
|
3136
|
+
const dateMatch = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
3137
|
+
if (dateMatch) {
|
|
3138
|
+
const [, year, month, day] = dateMatch;
|
|
3139
|
+
return new Date(
|
|
3140
|
+
parseInt(year),
|
|
3141
|
+
parseInt(month) - 1,
|
|
3142
|
+
parseInt(day),
|
|
3143
|
+
0,
|
|
3144
|
+
0,
|
|
3145
|
+
0
|
|
3146
|
+
);
|
|
3147
|
+
}
|
|
3148
|
+
return null;
|
|
3149
|
+
}
|
|
3150
|
+
function getRecentCommits(limit = 20) {
|
|
3151
|
+
const output = execOutput(`git log -${limit} --pretty=format:"%H|%s|%ai"`);
|
|
3152
|
+
if (!output) return [];
|
|
3153
|
+
return output.split("\n").map((line) => {
|
|
3154
|
+
const [hash, message, date] = line.split("|");
|
|
3155
|
+
return { hash, message, date };
|
|
3156
|
+
});
|
|
3157
|
+
}
|
|
3158
|
+
function getCommitByHash(hash) {
|
|
3159
|
+
try {
|
|
3160
|
+
const output = execOutput(`git log -1 ${hash} --pretty=format:"%H|%s|%ai"`);
|
|
3161
|
+
if (!output) return null;
|
|
3162
|
+
const [fullHash, message, date] = output.split("|");
|
|
3163
|
+
return { hash: fullHash, message, date };
|
|
3164
|
+
} catch {
|
|
3165
|
+
return null;
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
async function amendDate(commitHash) {
|
|
3169
|
+
console.log(colors.cyan("\u4FEE\u6539 Commit \u63D0\u4EA4\u65F6\u95F4"));
|
|
3170
|
+
divider();
|
|
3171
|
+
let selectedCommit;
|
|
3172
|
+
if (commitHash) {
|
|
3173
|
+
const commit2 = getCommitByHash(commitHash);
|
|
3174
|
+
if (!commit2) {
|
|
3175
|
+
console.log(colors.red(`\u2716 \u627E\u4E0D\u5230 commit: ${commitHash}`));
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
3178
|
+
selectedCommit = commit2;
|
|
3179
|
+
} else {
|
|
3180
|
+
const commits = getRecentCommits(20);
|
|
3181
|
+
if (commits.length === 0) {
|
|
3182
|
+
console.log(colors.yellow("\u6CA1\u6709\u627E\u5230\u4EFB\u4F55 commit"));
|
|
3183
|
+
return;
|
|
3184
|
+
}
|
|
3185
|
+
selectedCommit = await select8({
|
|
3186
|
+
message: "\u9009\u62E9\u8981\u4FEE\u6539\u65F6\u95F4\u7684 commit:",
|
|
3187
|
+
choices: commits.map((c) => ({
|
|
3188
|
+
name: `${colors.yellow(c.hash.slice(0, 7))} ${c.message.slice(0, 60)} ${colors.dim(c.date)}`,
|
|
3189
|
+
value: c,
|
|
3190
|
+
description: c.date
|
|
3191
|
+
})),
|
|
3192
|
+
pageSize: 15,
|
|
3193
|
+
theme
|
|
3194
|
+
});
|
|
3195
|
+
}
|
|
3196
|
+
console.log("");
|
|
3197
|
+
console.log("\u5F53\u524D commit \u4FE1\u606F:");
|
|
3198
|
+
console.log(` Hash: ${colors.yellow(selectedCommit.hash.slice(0, 7))}`);
|
|
3199
|
+
console.log(` Message: ${selectedCommit.message}`);
|
|
3200
|
+
console.log(` Date: ${colors.cyan(selectedCommit.date)}`);
|
|
3201
|
+
divider();
|
|
3202
|
+
console.log(colors.dim("\u8F93\u5165\u65E5\u671F\u683C\u5F0F: YYYY-MM-DD (\u5982: 2026-01-19)"));
|
|
3203
|
+
console.log("");
|
|
3204
|
+
const dateInput = await input6({
|
|
3205
|
+
message: "\u8F93\u5165\u65B0\u7684\u65E5\u671F:",
|
|
3206
|
+
validate: (value) => {
|
|
3207
|
+
const parsed = parseDate(value);
|
|
3208
|
+
if (!parsed) {
|
|
3209
|
+
return "\u65E5\u671F\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u8BF7\u4F7F\u7528 YYYY-MM-DD \u683C\u5F0F";
|
|
3210
|
+
}
|
|
3211
|
+
return true;
|
|
3212
|
+
},
|
|
3213
|
+
theme
|
|
3214
|
+
});
|
|
3215
|
+
const newDate = parseDate(dateInput);
|
|
3216
|
+
const formattedDate = formatGitDate(newDate);
|
|
3217
|
+
divider();
|
|
3218
|
+
console.log("\u4FEE\u6539\u9884\u89C8:");
|
|
3219
|
+
console.log(` Commit: ${colors.yellow(selectedCommit.hash.slice(0, 7))}`);
|
|
3220
|
+
console.log(` \u65E7\u65F6\u95F4: ${colors.dim(selectedCommit.date)}`);
|
|
3221
|
+
console.log(` \u65B0\u65F6\u95F4: ${colors.green(formattedDate)}`);
|
|
3222
|
+
console.log(` \u4FEE\u6539\u7C7B\u578B: Author + Committer (\u4E24\u8005\u90FD\u4FEE\u6539)`);
|
|
3223
|
+
divider();
|
|
3224
|
+
const latestHash = execOutput("git rev-parse HEAD");
|
|
3225
|
+
const isLatestCommit = selectedCommit.hash === latestHash;
|
|
3226
|
+
if (!isLatestCommit) {
|
|
3227
|
+
console.log(
|
|
3228
|
+
colors.yellow(
|
|
3229
|
+
"\u26A0\uFE0F \u8B66\u544A: \u4FEE\u6539\u975E\u6700\u65B0 commit \u9700\u8981\u4F7F\u7528 rebase\uFF0C\u53EF\u80FD\u4F1A\u6539\u53D8 commit hash"
|
|
3230
|
+
)
|
|
3231
|
+
);
|
|
3232
|
+
console.log(colors.dim(" \u8FD9\u4F1A\u5F71\u54CD\u5DF2\u63A8\u9001\u5230\u8FDC\u7A0B\u7684 commit\uFF0C\u8BF7\u8C28\u614E\u64CD\u4F5C"));
|
|
3233
|
+
console.log("");
|
|
3234
|
+
}
|
|
3235
|
+
const shouldProceed = await confirm({
|
|
3236
|
+
message: "\u786E\u8BA4\u4FEE\u6539?",
|
|
3237
|
+
default: false,
|
|
3238
|
+
theme
|
|
3239
|
+
});
|
|
3240
|
+
if (!shouldProceed) {
|
|
3241
|
+
console.log(colors.yellow("\u5DF2\u53D6\u6D88"));
|
|
3242
|
+
return;
|
|
3243
|
+
}
|
|
3244
|
+
try {
|
|
3245
|
+
if (isLatestCommit) {
|
|
3246
|
+
execSync9(
|
|
3247
|
+
`GIT_AUTHOR_DATE="${formattedDate}" GIT_COMMITTER_DATE="${formattedDate}" git commit --amend --no-edit --reset-author`,
|
|
3248
|
+
{ stdio: "pipe", shell: "/bin/bash" }
|
|
3249
|
+
);
|
|
3250
|
+
console.log("");
|
|
3251
|
+
console.log(colors.green("\u2714 \u4FEE\u6539\u6210\u529F"));
|
|
3252
|
+
} else {
|
|
3253
|
+
console.log("");
|
|
3254
|
+
console.log(colors.cyan("\u6B63\u5728\u6267\u884C rebase..."));
|
|
3255
|
+
const parentHash = execOutput(`git rev-parse ${selectedCommit.hash}^`);
|
|
3256
|
+
const filterCmd = `git filter-branch -f --env-filter 'if [ "$GIT_COMMIT" = "${selectedCommit.hash}" ]; then export GIT_AUTHOR_DATE="${formattedDate}"; export GIT_COMMITTER_DATE="${formattedDate}"; fi' ${parentHash}..HEAD`;
|
|
3257
|
+
execSync9(filterCmd, { stdio: "pipe" });
|
|
3258
|
+
console.log(colors.green("\u2714 \u4FEE\u6539\u6210\u529F"));
|
|
3259
|
+
console.log("");
|
|
3260
|
+
console.log(colors.yellow("\u26A0\uFE0F \u6CE8\u610F: commit hash \u5DF2\u6539\u53D8"));
|
|
3261
|
+
console.log(colors.dim(" \u5982\u679C\u5DF2\u63A8\u9001\u5230\u8FDC\u7A0B\uFF0C\u9700\u8981\u4F7F\u7528 force push:"));
|
|
3262
|
+
console.log(colors.cyan(" git push --force-with-lease"));
|
|
3263
|
+
}
|
|
3264
|
+
console.log("");
|
|
3265
|
+
} catch (error) {
|
|
3266
|
+
console.log("");
|
|
3267
|
+
console.log(colors.red("\u2716 \u4FEE\u6539\u5931\u8D25"));
|
|
3268
|
+
if (error instanceof Error) {
|
|
3269
|
+
console.log(colors.dim(error.message));
|
|
3270
|
+
}
|
|
3271
|
+
console.log("");
|
|
3272
|
+
throw error;
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
|
|
3276
|
+
// src/commands/amend.ts
|
|
3277
|
+
init_utils();
|
|
3278
|
+
import { execSync as execSync10 } from "child_process";
|
|
3279
|
+
import { select as select9, input as input7, confirm as confirm2 } from "@inquirer/prompts";
|
|
3280
|
+
function getRecentCommits2(limit = 20) {
|
|
3281
|
+
const output = execOutput(`git log -${limit} --pretty=format:"%H|%s|%ai"`);
|
|
3282
|
+
if (!output) return [];
|
|
3283
|
+
return output.split("\n").map((line) => {
|
|
3284
|
+
const [hash, message, date] = line.split("|");
|
|
3285
|
+
return { hash, message, date };
|
|
3286
|
+
});
|
|
3287
|
+
}
|
|
3288
|
+
function getCommitByHash2(hash) {
|
|
3289
|
+
try {
|
|
3290
|
+
const output = execOutput(`git log -1 ${hash} --pretty=format:"%H|%s|%ai"`);
|
|
3291
|
+
if (!output) return null;
|
|
3292
|
+
const [fullHash, message, date] = output.split("|");
|
|
3293
|
+
return { hash: fullHash, message, date };
|
|
3294
|
+
} catch {
|
|
3295
|
+
return null;
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
async function amend(commitHash) {
|
|
3299
|
+
console.log(colors.cyan("\u4FEE\u6539 Commit \u63D0\u4EA4\u4FE1\u606F"));
|
|
3300
|
+
divider();
|
|
3301
|
+
let selectedCommit;
|
|
3302
|
+
if (commitHash) {
|
|
3303
|
+
const commit2 = getCommitByHash2(commitHash);
|
|
3304
|
+
if (!commit2) {
|
|
3305
|
+
console.log(colors.red(`\u2716 \u627E\u4E0D\u5230 commit: ${commitHash}`));
|
|
3306
|
+
return;
|
|
3307
|
+
}
|
|
3308
|
+
selectedCommit = commit2;
|
|
3309
|
+
} else {
|
|
3310
|
+
const commits = getRecentCommits2(20);
|
|
3311
|
+
if (commits.length === 0) {
|
|
3312
|
+
console.log(colors.yellow("\u6CA1\u6709\u627E\u5230\u4EFB\u4F55 commit"));
|
|
3313
|
+
return;
|
|
3314
|
+
}
|
|
3315
|
+
selectedCommit = await select9({
|
|
3316
|
+
message: "\u9009\u62E9\u8981\u4FEE\u6539\u7684 commit:",
|
|
3317
|
+
choices: commits.map((c) => ({
|
|
3318
|
+
name: `${colors.yellow(c.hash.slice(0, 7))} ${c.message} ${colors.dim(c.date)}`,
|
|
3319
|
+
value: c,
|
|
3320
|
+
description: c.message
|
|
3321
|
+
})),
|
|
3322
|
+
pageSize: 15,
|
|
3323
|
+
theme
|
|
3324
|
+
});
|
|
3325
|
+
}
|
|
3326
|
+
console.log("");
|
|
3327
|
+
console.log("\u5F53\u524D commit \u4FE1\u606F:");
|
|
3328
|
+
console.log(` Hash: ${colors.yellow(selectedCommit.hash.slice(0, 7))}`);
|
|
3329
|
+
console.log(` Message: ${selectedCommit.message}`);
|
|
3330
|
+
console.log(` Date: ${colors.dim(selectedCommit.date)}`);
|
|
3331
|
+
divider();
|
|
3332
|
+
const newMessage = await input7({
|
|
3333
|
+
message: "\u8F93\u5165\u65B0\u7684 commit message:",
|
|
3334
|
+
default: selectedCommit.message,
|
|
3335
|
+
validate: (value) => {
|
|
3336
|
+
if (!value.trim()) {
|
|
3337
|
+
return "commit message \u4E0D\u80FD\u4E3A\u7A7A";
|
|
3338
|
+
}
|
|
3339
|
+
return true;
|
|
3340
|
+
},
|
|
3341
|
+
theme
|
|
3342
|
+
});
|
|
3343
|
+
divider();
|
|
3344
|
+
console.log("\u4FEE\u6539\u9884\u89C8:");
|
|
3345
|
+
console.log(
|
|
3346
|
+
` Commit: ${colors.yellow(selectedCommit.hash.slice(0, 7))}`
|
|
3347
|
+
);
|
|
3348
|
+
console.log(` \u65E7 Message: ${colors.dim(selectedCommit.message)}`);
|
|
3349
|
+
console.log(` \u65B0 Message: ${colors.green(newMessage)}`);
|
|
3350
|
+
divider();
|
|
3351
|
+
const latestHash = execOutput("git rev-parse HEAD");
|
|
3352
|
+
const isLatestCommit = selectedCommit.hash === latestHash;
|
|
3353
|
+
if (!isLatestCommit) {
|
|
3354
|
+
console.log(
|
|
3355
|
+
colors.yellow(
|
|
3356
|
+
"\u26A0\uFE0F \u8B66\u544A: \u4FEE\u6539\u975E\u6700\u65B0 commit \u9700\u8981\u4F7F\u7528 rebase\uFF0C\u53EF\u80FD\u4F1A\u6539\u53D8 commit hash"
|
|
3357
|
+
)
|
|
3358
|
+
);
|
|
3359
|
+
console.log(colors.dim(" \u8FD9\u4F1A\u5F71\u54CD\u5DF2\u63A8\u9001\u5230\u8FDC\u7A0B\u7684 commit\uFF0C\u8BF7\u8C28\u614E\u64CD\u4F5C"));
|
|
3360
|
+
console.log("");
|
|
3361
|
+
}
|
|
3362
|
+
const shouldProceed = await confirm2({
|
|
3363
|
+
message: "\u786E\u8BA4\u4FEE\u6539?",
|
|
3364
|
+
default: false,
|
|
3365
|
+
theme
|
|
3366
|
+
});
|
|
3367
|
+
if (!shouldProceed) {
|
|
3368
|
+
console.log(colors.yellow("\u5DF2\u53D6\u6D88"));
|
|
3369
|
+
return;
|
|
3370
|
+
}
|
|
3371
|
+
try {
|
|
3372
|
+
if (isLatestCommit) {
|
|
3373
|
+
execSync10(`git commit --amend -m "${newMessage.replace(/"/g, '\\"')}"`, {
|
|
3374
|
+
stdio: "pipe"
|
|
3375
|
+
});
|
|
3376
|
+
console.log("");
|
|
3377
|
+
console.log(colors.green("\u2714 \u4FEE\u6539\u6210\u529F"));
|
|
3378
|
+
} else {
|
|
3379
|
+
console.log("");
|
|
3380
|
+
console.log(colors.cyan("\u6B63\u5728\u6267\u884C rebase..."));
|
|
3381
|
+
const parentHash = execOutput(`git rev-parse ${selectedCommit.hash}^`);
|
|
3382
|
+
const rebaseScript = `#!/bin/sh
|
|
3383
|
+
if [ "$1" = "${selectedCommit.hash}" ]; then
|
|
3384
|
+
echo "${newMessage}" > "$2"
|
|
3385
|
+
fi
|
|
3386
|
+
`;
|
|
3387
|
+
const filterCmd = `git filter-branch -f --msg-filter 'if [ "$GIT_COMMIT" = "${selectedCommit.hash}" ]; then echo "${newMessage.replace(/"/g, '\\"')}"; else cat; fi' ${parentHash}..HEAD`;
|
|
3388
|
+
execSync10(filterCmd, { stdio: "pipe" });
|
|
3389
|
+
console.log(colors.green("\u2714 \u4FEE\u6539\u6210\u529F"));
|
|
3390
|
+
console.log("");
|
|
3391
|
+
console.log(colors.yellow("\u26A0\uFE0F \u6CE8\u610F: commit hash \u5DF2\u6539\u53D8"));
|
|
3392
|
+
console.log(colors.dim(" \u5982\u679C\u5DF2\u63A8\u9001\u5230\u8FDC\u7A0B\uFF0C\u9700\u8981\u4F7F\u7528 force push:"));
|
|
3393
|
+
console.log(colors.cyan(" git push --force-with-lease"));
|
|
3394
|
+
}
|
|
3395
|
+
console.log("");
|
|
3396
|
+
} catch (error) {
|
|
3397
|
+
console.log("");
|
|
3398
|
+
console.log(colors.red("\u2716 \u4FEE\u6539\u5931\u8D25"));
|
|
3399
|
+
if (error instanceof Error) {
|
|
3400
|
+
console.log(colors.dim(error.message));
|
|
3401
|
+
}
|
|
3402
|
+
console.log("");
|
|
3403
|
+
throw error;
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
|
|
3121
3407
|
// src/index.ts
|
|
3122
3408
|
process.on("uncaughtException", (err) => {
|
|
3123
3409
|
if (err instanceof ExitPromptError) {
|
|
@@ -3143,7 +3429,7 @@ process.on("SIGTERM", () => {
|
|
|
3143
3429
|
console.log("");
|
|
3144
3430
|
process.exit(0);
|
|
3145
3431
|
});
|
|
3146
|
-
var version = true ? "0.4.
|
|
3432
|
+
var version = true ? "0.4.3" : "0.0.0-dev";
|
|
3147
3433
|
async function mainMenu() {
|
|
3148
3434
|
console.log(
|
|
3149
3435
|
colors.green(`
|
|
@@ -3157,7 +3443,7 @@ async function mainMenu() {
|
|
|
3157
3443
|
);
|
|
3158
3444
|
console.log(colors.dim(` git-workflow v${colors.yellow(version)}
|
|
3159
3445
|
`));
|
|
3160
|
-
const action = await
|
|
3446
|
+
const action = await select10({
|
|
3161
3447
|
message: "\u9009\u62E9\u64CD\u4F5C:",
|
|
3162
3448
|
choices: [
|
|
3163
3449
|
{
|
|
@@ -3201,11 +3487,19 @@ async function mainMenu() {
|
|
|
3201
3487
|
value: "stash"
|
|
3202
3488
|
},
|
|
3203
3489
|
{
|
|
3204
|
-
name: `[b] \
|
|
3490
|
+
name: `[b] \u{1F4DC} \u67E5\u770B\u65E5\u5FD7 ${colors.dim("gw log")}`,
|
|
3205
3491
|
value: "log"
|
|
3206
3492
|
},
|
|
3207
3493
|
{
|
|
3208
|
-
name: `[c] \
|
|
3494
|
+
name: `[c] \u{1F550} \u4FEE\u6539\u63D0\u4EA4\u65F6\u95F4 ${colors.dim("gw ad")}`,
|
|
3495
|
+
value: "amend-date"
|
|
3496
|
+
},
|
|
3497
|
+
{
|
|
3498
|
+
name: `[d] \u270F\uFE0F \u4FEE\u6539\u63D0\u4EA4\u4FE1\u606F ${colors.dim("gw amend")}`,
|
|
3499
|
+
value: "amend"
|
|
3500
|
+
},
|
|
3501
|
+
{
|
|
3502
|
+
name: `[e] \u2699\uFE0F \u521D\u59CB\u5316\u914D\u7F6E ${colors.dim("gw init")}`,
|
|
3209
3503
|
value: "init"
|
|
3210
3504
|
},
|
|
3211
3505
|
{ name: "[0] \u2753 \u5E2E\u52A9", value: "help" },
|
|
@@ -3258,6 +3552,14 @@ async function mainMenu() {
|
|
|
3258
3552
|
checkGitRepo();
|
|
3259
3553
|
await log();
|
|
3260
3554
|
break;
|
|
3555
|
+
case "amend-date":
|
|
3556
|
+
checkGitRepo();
|
|
3557
|
+
await amendDate();
|
|
3558
|
+
break;
|
|
3559
|
+
case "amend":
|
|
3560
|
+
checkGitRepo();
|
|
3561
|
+
await amend();
|
|
3562
|
+
break;
|
|
3261
3563
|
case "init":
|
|
3262
3564
|
await init();
|
|
3263
3565
|
break;
|
|
@@ -3341,18 +3643,28 @@ cli.command("log", "\u4EA4\u4E92\u5F0FGit\u65E5\u5FD7\u67E5\u770B (\u5206\u9875\
|
|
|
3341
3643
|
if (options.limit) logOptions.limit = parseInt(options.limit);
|
|
3342
3644
|
return log(logOptions);
|
|
3343
3645
|
});
|
|
3646
|
+
cli.command("amend:date [hash]", "\u4FEE\u6539\u6307\u5B9A commit \u7684\u63D0\u4EA4\u65F6\u95F4").alias("ad").action(async (hash) => {
|
|
3647
|
+
await checkForUpdates(version, "@zjex/git-workflow");
|
|
3648
|
+
checkGitRepo();
|
|
3649
|
+
return amendDate(hash);
|
|
3650
|
+
});
|
|
3651
|
+
cli.command("amend [hash]", "\u4FEE\u6539\u6307\u5B9A commit \u7684\u63D0\u4EA4\u4FE1\u606F").action(async (hash) => {
|
|
3652
|
+
await checkForUpdates(version, "@zjex/git-workflow");
|
|
3653
|
+
checkGitRepo();
|
|
3654
|
+
return amend(hash);
|
|
3655
|
+
});
|
|
3344
3656
|
cli.command("clean", "\u6E05\u7406\u7F13\u5B58\u548C\u4E34\u65F6\u6587\u4EF6").alias("cc").action(async () => {
|
|
3345
3657
|
const { clearUpdateCache: clearUpdateCache3 } = await Promise.resolve().then(() => (init_update_notifier(), update_notifier_exports));
|
|
3346
3658
|
const { existsSync: existsSync5, unlinkSync: unlinkSync4, readdirSync } = await import("fs");
|
|
3347
3659
|
const { homedir: homedir5, tmpdir: tmpdir2 } = await import("os");
|
|
3348
3660
|
const { join: join6 } = await import("path");
|
|
3349
|
-
const { select:
|
|
3661
|
+
const { select: select11 } = await import("@inquirer/prompts");
|
|
3350
3662
|
let cleanedCount = 0;
|
|
3351
3663
|
let deletedGlobalConfig = false;
|
|
3352
3664
|
const globalConfig = join6(homedir5(), ".gwrc.json");
|
|
3353
3665
|
const hasGlobalConfig = existsSync5(globalConfig);
|
|
3354
3666
|
if (hasGlobalConfig) {
|
|
3355
|
-
const shouldDeleteConfig = await
|
|
3667
|
+
const shouldDeleteConfig = await select11({
|
|
3356
3668
|
message: "\u68C0\u6D4B\u5230\u5168\u5C40\u914D\u7F6E\u6587\u4EF6\uFF0C\u662F\u5426\u5220\u9664\uFF1F",
|
|
3357
3669
|
choices: [
|
|
3358
3670
|
{ name: "\u5426\uFF0C\u4FDD\u7559\u914D\u7F6E\u6587\u4EF6", value: false },
|
|
@@ -68,6 +68,8 @@ export default defineConfig({
|
|
|
68
68
|
{ text: "分支命令", link: "/commands/branch" },
|
|
69
69
|
{ text: "提交命令", link: "/commands/commit" },
|
|
70
70
|
{ text: "日志命令", link: "/commands/log" },
|
|
71
|
+
{ text: "修改提交信息", link: "/commands/amend" },
|
|
72
|
+
{ text: "修改提交时间", link: "/commands/amend-date" },
|
|
71
73
|
{ text: "Tag 命令", link: "/commands/tag" },
|
|
72
74
|
{ text: "Stash 命令", link: "/commands/stash" },
|
|
73
75
|
{ text: "版本命令", link: "/commands/release" },
|