@sppk/auto-git-flow 0.0.2 → 0.0.4
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/README.md +73 -47
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/package.json +27 -3
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
- 🛠 **命名规范化**: 自动生成符合团队约定的 `feat/`, `DEV-`, `RELEASE-` 分支名称。
|
|
12
12
|
- 🔄 **合并自动化**: 一键同步基准分支、合并代码并推送到远程,减少手工误操作。
|
|
13
|
+
- 🧠 **智能检测**: 自动检测分支落后状态,仅在必要时执行同步,避免冗余操作。
|
|
13
14
|
- 📋 **全景视图**: 快速查看当前项目的开发(Dev)与发布(Release)分支状态。
|
|
14
15
|
- 🛡 **安全检查**: 执行前自动检查工作区状态,确保代码提交安全。
|
|
15
16
|
- ⌨️ **交互式体验**: 基于 `@inquirer/prompts` 提供平滑的命令行交互。
|
|
@@ -34,41 +35,53 @@ pnpx agf --help
|
|
|
34
35
|
|
|
35
36
|
## 🛠 常用命令
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
agf
|
|
41
|
-
|
|
38
|
+
| 命令 | 说明 | 用法 |
|
|
39
|
+
| ------------ | ------------------------------------------------------- | -------------------------- |
|
|
40
|
+
| `agf list` | 展示最近的开发分支与发布分支列表 | `agf list [count]` |
|
|
41
|
+
| `agf create` | 根据类型(Feature/Dev/Release)和需求号自动生成规范分支 | `agf create` |
|
|
42
|
+
| `agf merge` | 将当前 Feature 分支合并到指定的目标分支 | `agf merge <dev\|release>` |
|
|
43
|
+
| `agf sync` | 同步基准分支代码到当前 Feature 分支 | `agf sync` |
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
### 命令详解
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
根据类型(Feature/Dev/Release)和需求号自动生成规范分支。
|
|
47
|
-
```bash
|
|
48
|
-
agf create
|
|
49
|
-
```
|
|
47
|
+
#### `agf list [count]`
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
查看最近的 Dev 与 Release 分支,默认显示最近 2 个。可用于检查 `agf` 识别的分支是否正确。
|
|
50
|
+
|
|
51
|
+
#### `agf create`
|
|
52
|
+
|
|
53
|
+
交互式创建分支,根据类型自动生成规范命名。
|
|
54
|
+
|
|
55
|
+
#### `agf merge <target>`
|
|
56
|
+
|
|
57
|
+
将当前 Feature 分支合并到目标分支(`dev` 或 `release`)。
|
|
58
|
+
|
|
59
|
+
**智能同步机制**:
|
|
60
|
+
|
|
61
|
+
- 自动检测目标分支是否落后于基准分支,仅在落后时执行同步
|
|
62
|
+
- 自动检测当前 Feature 分支是否落后于基准分支,必要时先同步 Feature
|
|
63
|
+
|
|
64
|
+
#### `agf sync`
|
|
65
|
+
|
|
66
|
+
手动同步基准分支(最新 Release)到当前 Feature 分支。如果当前分支已包含基准分支的所有提交,则跳过同步。
|
|
56
67
|
|
|
57
68
|
## 📋 命名规范
|
|
58
69
|
|
|
59
70
|
工具严格遵循以下命名约定:
|
|
60
71
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
| 分支类型 | 格式 | 示例 |
|
|
73
|
+
| -------- | ------------------------------- | ---------------------------- |
|
|
74
|
+
| Feature | `feat/<username>-<YYYYMMDD>-<reqNo>` | `feat/jack-20231024-QZ-8848` |
|
|
75
|
+
| Dev | `<project>-DEV-<YYYYMMDD>` | `mall-DEV-20231024` |
|
|
76
|
+
| Release | `<project>-RELEASE-<YYYYMMDD>` | `mall-RELEASE-20231024` |
|
|
77
|
+
|
|
78
|
+
> **需求编号格式**: `QZ-` 后跟 4~8 位数字(如 `QZ-8848` 或 `QZ-12345678`)
|
|
67
79
|
|
|
68
80
|
## 📐 工作流图解
|
|
69
81
|
|
|
70
82
|
### 分支创建流程 (Create)
|
|
71
|
-
|
|
83
|
+
|
|
84
|
+
所有分支创建后都会自动推送到远程。`dev` 或 `release` 分支推送后切回原分支;`feature` 分支则留在新分支继续开发。
|
|
72
85
|
|
|
73
86
|
```mermaid
|
|
74
87
|
graph TD
|
|
@@ -78,46 +91,59 @@ graph TD
|
|
|
78
91
|
Fetch --> Config[采集配置: 类型/日期/需求号]
|
|
79
92
|
Config --> Name[生成规范名称]
|
|
80
93
|
Name --> Checkout[从 Base 分支创建并切换]
|
|
81
|
-
Checkout -->
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
TypeCheck --
|
|
85
|
-
|
|
94
|
+
Checkout --> Push[推送到远程]
|
|
95
|
+
Push --> TypeCheck{分支类型?}
|
|
96
|
+
|
|
97
|
+
TypeCheck -- Feature --> DoneFeature([留在新分支, 完成])
|
|
98
|
+
TypeCheck -- Dev/Release --> Back[切回原分支]
|
|
86
99
|
Back --> DoneOther([完成])
|
|
87
100
|
```
|
|
88
101
|
|
|
89
102
|
### 分支合并流程 (Merge)
|
|
90
|
-
|
|
103
|
+
|
|
104
|
+
将当前特性分支合并到目标环境。会**智能检测**分支落后状态,仅在必要时执行同步。
|
|
105
|
+
|
|
106
|
+
**基准分支选择逻辑**:
|
|
107
|
+
- 合并到 **Dev** 时:基准为**最新 Release** 分支
|
|
108
|
+
- 合并到 **Release** 时:基准为**上一个 Release** 分支(避免将未发布的代码带入)
|
|
91
109
|
|
|
92
110
|
```mermaid
|
|
93
111
|
graph TD
|
|
94
112
|
Start([开始合并]) --> CheckClean{检查工作区}
|
|
95
113
|
CheckClean -- 脏 --> Error([提示保存并退出])
|
|
96
114
|
CheckClean -- 干净 --> CheckType{当前是 Feature?}
|
|
97
|
-
|
|
115
|
+
|
|
98
116
|
CheckType -- 否 --> ErrorType([只允许从 Feature 发起])
|
|
99
|
-
CheckType -- 是 -->
|
|
100
|
-
|
|
117
|
+
CheckType -- 是 --> ConfirmRelease{目标是 Release?}
|
|
118
|
+
|
|
119
|
+
ConfirmRelease -- 是 --> UserConfirm[二次人工确认]
|
|
120
|
+
ConfirmRelease -- 否 --> FindTarget
|
|
121
|
+
UserConfirm -- 取消 --> End([结束])
|
|
122
|
+
UserConfirm -- 确认 --> FindTarget[定位目标分支]
|
|
123
|
+
|
|
101
124
|
FindTarget --> Exist{目标分支存在?}
|
|
102
125
|
Exist -- 否 --> CreateNew[引导创建并推送]
|
|
103
|
-
Exist -- 是 -->
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
126
|
+
Exist -- 是 --> Pull[拉取远程最新代码]
|
|
127
|
+
CreateNew --> Pull
|
|
128
|
+
|
|
129
|
+
Pull --> CheckTargetBehind{目标落后于基准?}
|
|
130
|
+
CheckTargetBehind -- 是 --> SyncTarget[同步: 基准 → 目标]
|
|
131
|
+
CheckTargetBehind -- 否 --> SkipTargetSync[跳过目标同步]
|
|
132
|
+
SyncTarget --> CheckFeatureBehind
|
|
133
|
+
SkipTargetSync --> CheckFeatureBehind{Feature 落后于基准?}
|
|
134
|
+
|
|
135
|
+
CheckFeatureBehind -- 是 --> SyncFeature[同步: 基准 → Feature]
|
|
136
|
+
CheckFeatureBehind -- 否 --> SkipFeatureSync[跳过 Feature 同步]
|
|
137
|
+
SyncFeature --> DoMerge
|
|
138
|
+
SkipFeatureSync --> DoMerge[执行合并]
|
|
139
|
+
|
|
140
|
+
DoMerge --> MergeFeat[Feature → 目标]
|
|
115
141
|
MergeFeat --> Push[推送目标分支]
|
|
116
142
|
Push --> Back[切回 Feature 分支]
|
|
117
143
|
Back --> Done([合并完成])
|
|
118
144
|
|
|
119
145
|
classDef highlight fill:#f96,stroke:#333,stroke-width:2px
|
|
120
|
-
|
|
146
|
+
classDef smart fill:#69f,stroke:#333,stroke-width:2px
|
|
147
|
+
class UserConfirm highlight
|
|
148
|
+
class CheckTargetBehind,CheckFeatureBehind smart
|
|
121
149
|
```
|
|
122
|
-
|
|
123
|
-
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as
|
|
3
|
-
\u8BF7\u624B\u52A8\u89E3\u51B3\u51B2\u7A81\u6587\u4EF6\u5E76\u63D0\u4EA4\uFF0C\u7136\u540E\u5207\u6362\u56DE\u539F\u5206\u652F\u3002`)}}async function
|
|
4
|
-
${
|
|
5
|
-
`))},warn:e=>console.log(`${
|
|
6
|
-
`)};async function
|
|
2
|
+
import{Command as te}from"commander";import{createRequire as re}from"module";import{input as j,select as X}from"@inquirer/prompts";import{format as K}from"date-fns";import{simpleGit as N}from"simple-git";import k from"chalk";var F=null;function s(){return F||(F=N()),F}async function T(){if(!(await s().status()).isClean())throw new Error("\u274C \u5DE5\u4F5C\u533A\u6709\u672A\u63D0\u4EA4\u7684\u4EE3\u7801\uFF0C\u8BF7\u5148 Commit \u6216 Stash\u3002")}async function V(){let e=await s().getConfig("user.name");if(!e.value)throw new Error("\u274C \u83B7\u53D6\u4E0D\u5230\u7528\u6237\u540D\uFF0C\u8BF7\u6267\u884C git config user.name \u914D\u7F6E\u3002");return e.value}async function g(){console.log(k.gray("\u6B63\u5728\u62C9\u53D6\u8FDC\u7A0B\u6700\u65B0\u5206\u652F\u5217\u8868...")),await s().fetch(["--prune"])}async function p(){return(await s().branch()).current}async function u(e,r=!1,n){if(r)if(n){let a=await s().branch(),o=`remotes/origin/${n}`;if(!a.all.includes(o))throw new Error(`\u274C \u9519\u8BEF: \u8FDC\u7A0B\u5206\u652F origin/${n} \u4E0D\u5B58\u5728`);await s().checkout(["-b",e,"--no-track",`origin/${n}`])}else await s().checkoutLocalBranch(e);else await s().checkout(e)}async function x(e,r){try{await s().merge([r])}catch(n){throw console.error(n),new Error(`\u26A0\uFE0F \u53D1\u751F\u4EE3\u7801\u51B2\u7A81\uFF01\u4ECE ${r} \u5408\u5E76\u5230 ${e} \u5931\u8D25\u3002
|
|
3
|
+
\u8BF7\u624B\u52A8\u89E3\u51B3\u51B2\u7A81\u6587\u4EF6\u5E76\u63D0\u4EA4\uFF0C\u7136\u540E\u5207\u6362\u56DE\u539F\u5206\u652F\u3002`)}}async function d(e){await s().push(["-u","origin",e])}async function A(e){let r=await s().branch();if(r.all.includes(e))console.log(k.gray(`\u6B63\u5728\u66F4\u65B0\u672C\u5730\u5206\u652F ${e}...`)),await s().checkout(e),await s().pull("origin",e);else if(r.all.includes(`remotes/origin/${e}`))console.log(k.gray(`\u6B63\u5728\u4ECE\u8FDC\u7A0B\u62C9\u53D6\u5206\u652F ${e}...`)),await s().checkout(["-b",e,`origin/${e}`]);else throw new Error(`\u274C \u9519\u8BEF: \u8FDC\u7A0B\u4E0D\u5B58\u5728\u5206\u652F ${e}`)}async function h(){let e=await s().branch(["-a"]);return Array.from(new Set(e.all.map(r=>r.replace("remotes/origin/",""))))}async function D(e,r){let n=`origin/${e}`,a=`origin/${r}`,o=await s().raw(["rev-list","--count",`${n}..${a}`]);return parseInt(o.trim(),10)>0}import{compareDesc as S,compareAsc as O,parse as M}from"date-fns";var P=/^QZ-\d{4,8}$/;function y(e){let r=e.match(/^(.+)-RELEASE-(\d{8})$/);if(r)return{name:e,type:"RELEASE",project:r[1],date:M(r[2],"yyyyMMdd",new Date)};let n=e.match(/^(.+)-(?:DEV|dev)-(\d{8})$/);if(n)return{name:e,type:"DEV",project:n[1],date:M(n[2],"yyyyMMdd",new Date)};let a=e.match(/^feat\/(.+)-(\d{8})-(QZ-\d{4})$/);return a?{name:e,type:"FEATURE",date:M(a[2],"yyyyMMdd",new Date)}:null}function I(e){return e.map(y).filter(n=>n?.type==="RELEASE").sort((n,a)=>S(n.date,a.date))[0]||null}function Q(e){return e.map(y).filter(n=>n?.type==="RELEASE").sort((n,a)=>S(n.date,a.date))[1]||null}function U(e,r){let n=new Date,a=new Date(n.getFullYear(),n.getMonth(),n.getDate());return e.map(y).filter(i=>i?.type===r&&!!i.date).filter(i=>i.date>=a).sort((i,c)=>O(i.date,c.date))[0]||null}function b(e,r,n){return e.map(y).filter(a=>a?.type===r).sort((a,o)=>S(a.date,o.date)).slice(0,n)}import f from"chalk";var w=f.gray("\u2502"),t={header:e=>{console.log(`
|
|
4
|
+
${f.bgCyan.black.bold(" GIT-FLOW ")} ${f.cyan.bold(e)}`),console.log(w)},info:e=>console.log(`${w} ${f.blue("\u2139")} ${e}`),step:e=>{process.stdout.write(`${w} ${f.yellow("\u279C")} ${e}`)},success:e=>console.log(`${w} ${f.green("\u2714")} ${e}`),done:()=>{process.stdout.write(f.green(` [OK]
|
|
5
|
+
`))},warn:e=>console.log(`${w} ${f.yellow("\u26A0")} ${e}`),error:e=>console.error(`${w} ${f.red("\u2718")} ${e}`),errorRaw:e=>console.error(`${w} ${f.red(e)}`),dim:e=>console.log(`${w} ${f.gray(e)}`),dimRaw:e=>{process.stdout.write(`${w} ${f.gray(e)}`)},footer:()=>console.log(w+`
|
|
6
|
+
`)};async function W(e){let r=await p(),n=await h(),a=I(n),o=a?.name||r;t.info(`\u5F53\u524D\u5206\u652F: ${r}`),a?t.info(`\u57FA\u51C6\u5206\u652F: ${a.name}`):t.warn("\u672A\u627E\u5230 Release \u5206\u652F\uFF0C\u5C06\u4EE5\u5F53\u524D\u5206\u652F\u4E3A\u57FA\u51C6");let i=e||await X({message:"\u8BF7\u9009\u62E9\u8981\u521B\u5EFA\u7684\u5206\u652F\u7C7B\u578B:",choices:[{name:"Feature (\u7279\u6027\u5F00\u53D1)",value:"FEATURE"},{name:"Dev (\u6D4B\u8BD5\u73AF\u5883)",value:"DEV"},{name:"Release (\u751F\u4EA7\u73AF\u5883)",value:"RELEASE"}]}),c=K(new Date,"yyyyMMdd"),$=await j({message:`\u8BF7\u8F93\u5165\u65E5\u671F (\u683C\u5F0F: YYYYMMDD, \u9ED8\u8BA4: ${c}):`,default:c,validate:l=>/^\d{8}$/.test(l)?l<c?`\u274C \u65E5\u671F\u8FC7\u65E9: \u65E5\u671F\u5FC5\u987B\u5927\u4E8E\u6216\u7B49\u4E8E\u5F53\u524D\u65E5\u671F (${c})`:!0:"\u274C \u683C\u5F0F\u9519\u8BEF: \u8BF7\u8F93\u51658\u4F4D\u6570\u5B57\u65E5\u671F"}),E=a?.project||"";i!=="FEATURE"&&!E&&(E=await j({message:"\u8BF7\u8F93\u5165\u9879\u76EE\u540D\u79F0:",validate:l=>l.trim()?!0:"\u274C \u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A"}));let m;return i==="FEATURE"&&(m=await j({message:"\u8BF7\u8F93\u5165\u9700\u6C42\u7F16\u53F7 (\u4F8B\u5982 QZ-8848):",validate:l=>P.test(l)||"\u274C \u683C\u5F0F\u9519\u8BEF: \u9700\u6C42\u7F16\u53F7\u5FC5\u987B\u4E3A QZ \u540E\u63A54-8\u4F4D\u6570\u5B57 (\u5982 QZ-8848)"})),{type:i,baseBranch:o,project:E,date:$,reqNo:m}}async function L(e){let r=typeof e=="string"?e:void 0;try{t.header("\u521B\u5EFA\u5206\u652F"),await T(),await g();let n=await p(),a=await W(r),{type:o,baseBranch:i,project:c,date:$,reqNo:E}=a,m;o==="FEATURE"?m=`feat/${await V()}-${$}-${E}`:m=`${c}-${o}-${$}`,t.step(`\u6B63\u5728\u4ECE ${i} \u521B\u5EFA ${m}...`),await u(m,!0,i),await d(m),t.done(),o==="FEATURE"?t.success(`\u5206\u652F ${m} \u521B\u5EFA\u6210\u529F\u5E76\u5DF2\u63A8\u9001\u5230\u8FDC\u7A0B\uFF0C\u5DF2\u5207\u6362\u81F3\u8BE5\u5206\u652F`):(t.success(`\u5206\u652F ${m} \u521B\u5EFA\u6210\u529F\u5E76\u5DF2\u63A8\u9001\u5230\u8FDC\u7A0B`),n!==await p()&&(t.dimRaw(`\u6B63\u5728\u5207\u56DE\u539F\u5206\u652F ${n}...`),await u(n),t.done())),t.footer()}catch(n){t.errorRaw(n.message),t.footer()}}import{confirm as q}from"@inquirer/prompts";async function z(e){await g();let r=await h(),n=U(r,e);if(n||(t.warn(`\u672A\u627E\u5230\u53EF\u7528\u7684 ${e} \u5206\u652F\uFF08\u9700\u4E3A\u4ECA\u65E5\u6216\u672A\u6765\u65F6\u95F4\uFF09\u3002`),await q({message:`\u786E\u5B9A\u8981\u73B0\u5728\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684 ${e} \u5206\u652F\u5417\uFF1F`,default:!0})&&(await L(e),await g(),r=await h(),n=U(r,e))),!n)throw new Error(`\u7EC8\u6B62: \u672A\u80FD\u5B9A\u4F4D\u5230\u6709\u6548\u7684 ${e} \u76EE\u6807\u5206\u652F\u3002`);return n}async function H(e,r,n){t.step("\u6B63\u5728\u540C\u6B65\u8FDC\u7A0B\u4EE3\u7801..."),await A(e.name),r&&(await A(r.name),await A(n)),t.done(),r&&(await D(e.name,r.name)?(t.step(`\u6B63\u5728\u540C\u6B65\u57FA\u51C6 ${r.name} -> ${e.name}...`),await u(e.name),await x(e.name,r.name),await d(e.name),t.done()):t.dim(`${e.name} \u5DF2\u5305\u542B ${r.name} \u7684\u6240\u6709\u63D0\u4EA4\uFF0C\u8DF3\u8FC7\u540C\u6B65`),await D(n,r.name)&&(t.step(`\u68C0\u6D4B\u5230 ${n} \u843D\u540E\u4E8E ${r.name}\uFF0C\u6B63\u5728\u540C\u6B65...`),await u(n),await x(n,r.name),await d(n),t.done()))}async function Y(e){let r=await p();try{await T(),t.header("\u5408\u5E76\u5206\u652F"),await g();let n=y(r);if(!n||n.type!=="FEATURE")throw new Error("\u7981\u6B62\u64CD\u4F5C\uFF1A\u8BF7\u5148\u5207\u6362\u5230 Feature \u5206\u652F\u518D\u6267\u884C\u5408\u5E76\u3002");let a=e==="dev"?"DEV":e==="release"?"RELEASE":null;if(!a)throw new Error("\u9519\u8BEF\u53C2\u6570\uFF1A\u8BF7\u6307\u5B9A\u5408\u5E76\u76EE\u6807 (dev \u6216 release)\u3002");t.info(`\u5F53\u524D\u5206\u652F: ${r}`);let o=await z(a),i=await h(),c=a==="DEV"?I(i):Q(i);if(t.info(`\u76EE\u6807\u73AF\u5883: ${o.name}${c?` (\u57FA\u51C6: ${c.name})`:""}`),a==="RELEASE"&&!await q({message:`\u26A0\uFE0F \u786E\u5B9A\u8981\u5C06\u7279\u6027\u5206\u652F\u5408\u5E76\u5230\u751F\u4EA7\u73AF\u5883 ${o.name} \u5417\uFF1F`,default:!1})){t.dim("\u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002"),t.footer();return}await H(o,c,r),t.step(`\u6B63\u5728\u5408\u5E76 Feature \u5230 ${o.name}...`),await u(o.name),await x(o.name,r),t.done(),t.step("\u6B63\u5728\u63A8\u9001\u5230\u8FDC\u7A0B..."),await d(o.name),t.done(),await u(r),t.success(`\u6210\u529F\uFF01Feature \u5DF2\u5408\u5E76\u81F3 ${o.name} \u5E76\u63A8\u9001\u5230 origin\u3002`),t.dim(`\u5DF2\u81EA\u52A8\u5207\u56DE ${r}`),t.footer()}catch(n){t.errorRaw(n.message),await p()!==r&&t.warn(`\u6D41\u7A0B\u4E2D\u65AD\uFF0C\u7531\u4E8E\u4EE3\u7801\u51B2\u7A81\u6216\u5176\u4ED6\u9519\u8BEF\uFF0C\u8BF7\u624B\u52A8\u5904\u7406\u540E\u5207\u56DE ${r}\u3002`),t.footer()}}import J from"cli-table3";import v from"chalk";import{format as ee}from"date-fns";async function Z(e){try{await g();let r=await h(),n=parseInt(e,10),a=b(r,"RELEASE",n),o=b(r,"DEV",n);t.header(`\u5206\u652F\u5217\u8868 (Latest ${n})`);let i=new J({head:[v.cyan("Type"),v.cyan("Branch Name"),v.cyan("Date"),v.cyan("Project")],style:{head:[],border:[]}}),c=($,E,m)=>{$.forEach(l=>{i.push([m(E),l.name,l.date?ee(l.date,"yyyy-MM-dd"):"-",l.project||"-"])})};if(c(a,"Release",v.green),c(o,"Dev",v.yellow),i.length===0){t.warn("\u672A\u53D1\u73B0\u7B26\u5408\u89C4\u8303\u7684 dev \u6216 release \u5206\u652F\u3002"),t.footer();return}console.log(i.toString()),t.footer()}catch(r){t.errorRaw(`\u83B7\u53D6\u5206\u652F\u5217\u8868\u5931\u8D25: ${r.message}`),t.footer()}}async function _(){let e=await p();try{await T(),t.header("\u540C\u6B65\u57FA\u51C6\u5206\u652F"),await g();let r=y(e);if(!r||r.type!=="FEATURE")throw new Error("\u7981\u6B62\u64CD\u4F5C\uFF1A\u8BF7\u5148\u5207\u6362\u5230 Feature \u5206\u652F\u518D\u6267\u884C\u540C\u6B65\u3002");t.info(`\u5F53\u524D\u5206\u652F: ${e}`);let n=await h(),a=I(n);if(!a)throw new Error("\u672A\u627E\u5230\u53EF\u7528\u7684 Release \u57FA\u51C6\u5206\u652F\u3002");if(t.info(`\u57FA\u51C6\u5206\u652F: ${a.name}`),t.step("\u6B63\u5728\u62C9\u53D6\u8FDC\u7A0B\u4EE3\u7801..."),await A(a.name),await A(e),t.done(),!await D(e,a.name)){t.success(`\u5F53\u524D\u5206\u652F ${e} \u5DF2\u5305\u542B ${a.name} \u7684\u6240\u6709\u63D0\u4EA4\uFF0C\u65E0\u9700\u540C\u6B65\u3002`),t.footer();return}t.step(`\u6B63\u5728\u5408\u5E76 ${a.name} -> ${e}...`),await u(e),await x(e,a.name),t.done(),t.step("\u6B63\u5728\u63A8\u9001\u5230\u8FDC\u7A0B..."),await d(e),t.done(),t.success(`\u6210\u529F\uFF01${a.name} \u5DF2\u5408\u5E76\u81F3 ${e} \u5E76\u63A8\u9001\u5230 origin\u3002`),t.footer()}catch(r){t.errorRaw(r.message),await p()!==e&&t.warn(`\u6D41\u7A0B\u4E2D\u65AD\uFF0C\u7531\u4E8E\u4EE3\u7801\u51B2\u7A81\u6216\u5176\u4ED6\u9519\u8BEF\uFF0C\u8BF7\u624B\u52A8\u5904\u7406\u540E\u5207\u56DE ${e}\u3002`),t.footer()}}var ne=re(import.meta.url),{version:ae}=ne("../package.json"),C=new te;C.name("agf").description("Auto Git Flow CLI - \u81EA\u52A8\u5316 Git \u5206\u652F\u7BA1\u7406\u5DE5\u5177").version(ae);C.command("create").description("\u521B\u5EFA\u65B0\u5206\u652F (Release, Dev, Feature)").action(L);C.command("merge").description("\u5408\u5E76\u5206\u652F (Safe-Merge \u7B56\u7565)").argument("<target>","\u76EE\u6807\u73AF\u5883 (dev \u6216 release)").action(Y);C.command("list").description("\u67E5\u770B\u6700\u65B0\u7684 dev \u548C release \u5206\u652F").argument("[count]","\u5217\u51FA\u7684\u5206\u652F\u4E2A\u6570 (\u9ED8\u8BA4 2)","2").action(Z);C.command("sync").description("\u540C\u6B65\u57FA\u51C6\u5206\u652F\u5230\u5F53\u524D Feature \u5206\u652F").action(_);C.parse();
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/utils/git.ts","../src/utils/branch.ts","../src/utils/ui.ts","../src/commands/merge.ts","../src/commands/list.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { createAction } from './commands/create.js';\nimport { mergeAction } from './commands/merge.js';\nimport { listAction } from './commands/list.js';\n\nconst program = new Command();\n\nprogram\n .name('agf')\n .description('Auto Git Flow CLI - 自动化 Git 分支管理工具')\n .version('1.0.0');\n\nprogram\n .command('create')\n .description('创建新分支 (Release, Dev, Feature)')\n .action(createAction);\n\nprogram\n .command('merge')\n .description('合并分支 (Safe-Merge 策略)')\n .argument('<target>', '目标环境 (dev 或 release)')\n .action(mergeAction);\n\nprogram\n .command('list')\n .description('查看最新的 dev 和 release 分支')\n .argument('[count]', '列出的分支个数 (默认 2)', '2')\n .action(listAction);\n\nprogram.parse();\n","import { input, select } from '@inquirer/prompts';\nimport { format } from 'date-fns';\nimport { \n checkClean, \n fetchRemote, \n getBranches, \n getUserName, \n checkout, \n push,\n getCurrentBranch\n} from '../utils/git.js';\nimport { \n getLatestRelease, \n REQ_NO_REGEX, \n BranchType \n} from '../utils/branch.js';\nimport { logger } from '../utils/ui.js';\n\ninterface CreateConfig {\n type: BranchType;\n baseBranch: string;\n project: string;\n date: string;\n reqNo?: string | undefined;\n}\n\nasync function getCreateConfig(forcedType?: BranchType): Promise<CreateConfig> {\n const originalBranch = await getCurrentBranch();\n const branches = await getBranches();\n const latestRelease = getLatestRelease(branches);\n const baseBranch = latestRelease?.name || originalBranch;\n\n logger.info(`当前分支: ${originalBranch}`);\n if (latestRelease) {\n logger.info(`基准分支: ${latestRelease.name}`);\n } else {\n logger.warn('未找到 Release 分支,将以当前分支为基准');\n }\n\n const type = forcedType || await select({\n message: '请选择要创建的分支类型:',\n choices: [\n { name: 'Feature (特性开发)', value: BranchType.FEATURE },\n { name: 'Dev (测试环境)', value: BranchType.DEV },\n { name: 'Release (生产环境)', value: BranchType.RELEASE },\n ],\n });\n\n const project = latestRelease?.project || 'mall';\n const today = format(new Date(), 'yyyyMMdd');\n\n const dateInput = await input({\n message: `请输入日期 (格式: YYYYMMDD, 默认: ${today}):`,\n default: today,\n validate: (value) => {\n if (!/^\\d{8}$/.test(value)) return '❌ 格式错误: 请输入8位数字日期';\n if (value < today) return `❌ 日期过早: 日期必须大于或等于当前日期 (${today})`;\n return true;\n },\n });\n\n let reqNo;\n if (type === BranchType.FEATURE) {\n reqNo = await input({\n message: '请输入需求编号 (例如 QZ-8848):',\n validate: (input) => REQ_NO_REGEX.test(input) || '❌ 格式错误: 需求编号必须为 QZ 后接4位数字 (如 QZ-8848)',\n });\n }\n\n return { type, baseBranch, project, date: dateInput, reqNo };\n}\n\nexport async function createAction(arg?: BranchType | any) {\n // Commander passes the Command object if no args are defined, so we need to filter that out\n const forcedType = typeof arg === 'string' ? arg as BranchType : undefined;\n try {\n logger.header('创建分支');\n await checkClean();\n await fetchRemote();\n\n const originalBranch = await getCurrentBranch();\n const config = await getCreateConfig(forcedType);\n const { type, baseBranch, project, date, reqNo } = config;\n\n let branchName: string;\n if (type === BranchType.FEATURE) {\n const user = await getUserName();\n branchName = `feat/${user}-${date}-${reqNo}`;\n } else {\n branchName = `${project}-${type}-${date}`;\n }\n\n logger.step(`正在从 ${baseBranch} 创建 ${branchName}...`);\n await checkout(branchName, true, baseBranch);\n \n if (type !== BranchType.FEATURE) {\n await push(branchName);\n }\n logger.done();\n\n if (type === BranchType.FEATURE) {\n logger.success('分支创建成功,已切换至该分支');\n } else {\n logger.success('分支创建成功并已推送到远程');\n \n // 非特性分支创建后切回原分支\n if (originalBranch !== (await getCurrentBranch())) {\n logger.dimRaw(`正在切回原分支 ${originalBranch}...`);\n await checkout(originalBranch);\n logger.done();\n }\n }\n\n logger.footer();\n\n } catch (err: any) {\n logger.errorRaw(err.message);\n logger.footer();\n }\n}\n","import { simpleGit, type SimpleGit } from 'simple-git';\nimport chalk from 'chalk';\n\nconst git: SimpleGit = simpleGit();\n\nexport async function checkClean() {\n const status = await git.status();\n if (!status.isClean()) {\n throw new Error('❌ 工作区有未提交的代码,请先 Commit 或 Stash。');\n }\n}\n\nexport async function getUserName(): Promise<string> {\n const name = await git.getConfig('user.name');\n if (!name.value) {\n throw new Error('❌ 获取不到用户名,请执行 git config user.name 配置。');\n }\n return name.value;\n}\n\nexport async function fetchRemote() {\n console.log(chalk.gray('正在拉取远程最新分支列表...'));\n await git.fetch(['--prune']);\n}\n\nexport async function getCurrentBranch(): Promise<string> {\n const branchInfo = await git.branch();\n return branchInfo.current;\n}\n\nexport async function checkout(branch: string, create = false, startPoint?: string) {\n if (create) {\n if (startPoint) {\n await git.checkout(['-b', branch, startPoint]);\n } else {\n await git.checkoutLocalBranch(branch);\n }\n } else {\n await git.checkout(branch);\n }\n}\n\nexport async function merge(target: string, source: string) {\n try {\n await git.merge([source]);\n } catch (err: any) {\n throw new Error(`⚠️ 发生代码冲突!从 ${source} 合并到 ${target} 失败。\\n请手动解决冲突文件并提交,然后切换回原分支。`);\n }\n}\n\nexport async function push(branch: string) {\n await git.push(['-u', 'origin', branch]);\n}\n\nexport async function pullBranch(branch: string) {\n const branches = await git.branch();\n const isLocal = branches.all.includes(branch);\n \n if (!isLocal) {\n // Check if remote exists\n const remoteExists = branches.all.includes(`remotes/origin/${branch}`);\n if (remoteExists) {\n console.log(chalk.gray(`正在从远程拉取分支 ${branch}...`));\n await git.checkout(['-b', branch, `origin/${branch}`]);\n } else {\n throw new Error(`❌ 错误: 远程不存在分支 ${branch}`);\n }\n } else {\n console.log(chalk.gray(`正在更新本地分支 ${branch}...`));\n await git.checkout(branch);\n await git.pull('origin', branch);\n }\n}\n\nexport async function getBranches() {\n const summary = await git.branch(['-a']);\n return Array.from(new Set(summary.all.map(b => b.replace('remotes/origin/', ''))));\n}\n\nexport { git };\n","import { compareDesc, compareAsc, parse } from 'date-fns';\n\nexport enum BranchType {\n RELEASE = 'RELEASE',\n DEV = 'DEV',\n FEATURE = 'FEATURE'\n}\n\nexport const REQ_NO_REGEX = /^QZ-\\d{4}$/;\n\nexport interface BranchInfo {\n name: string;\n type: BranchType;\n date?: Date;\n project?: string;\n}\n\nexport function parseBranch(branchName: string): BranchInfo | null {\n // Release: {project}-RELEASE-{YYYYMMDD}\n const releaseMatch = branchName.match(/^(.+)-RELEASE-(\\d{8})$/);\n if (releaseMatch) {\n return {\n name: branchName,\n type: BranchType.RELEASE,\n project: releaseMatch[1]!,\n date: parse(releaseMatch[2]!, 'yyyyMMdd', new Date())\n };\n }\n\n // Dev: {project}-DEV-{YYYYMMDD}\n // {project}-dev-{YYYYMMDD}\n const devMatch = branchName.match(/^(.+)-(?:DEV|dev)-(\\d{8})$/);\n if (devMatch) {\n return {\n name: branchName,\n type: BranchType.DEV,\n project: devMatch[1]!,\n date: parse(devMatch[2]!, 'yyyyMMdd', new Date())\n };\n }\n\n // Feature: feat/{user}-{date}-{reqNo}\n const featMatch = branchName.match(/^feat\\/(.+)-(\\d{8})-(QZ-\\d{4})$/);\n if (featMatch) {\n return {\n name: branchName,\n type: BranchType.FEATURE,\n date: parse(featMatch[2]!, 'yyyyMMdd', new Date())\n };\n }\n\n return null;\n}\n\nexport function getLatestRelease(branches: string[]): BranchInfo | null {\n const releases = branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === BranchType.RELEASE)\n .sort((a, b) => compareDesc(a.date!, b.date!));\n\n return releases[0] || null;\n}\n\nexport function getPreviousRelease(branches: string[]): BranchInfo | null {\n const releases = branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === BranchType.RELEASE)\n .sort((a, b) => compareDesc(a.date!, b.date!));\n\n return releases[1] || null;\n}\n\nexport function getTargetBranch(branches: string[], type: BranchType): BranchInfo | null {\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); // Start of today\n\n const targets = branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === type && !!b.date)\n .filter(b => b.date! >= today) // Only today or future\n .sort((a, b) => compareAsc(a.date!, b.date!));\n\n return targets[0] || null; // Return the earliest one (which is the closest to today)\n}\nexport function getLatestBranches(branches: string[], type: BranchType, limit: number): BranchInfo[] {\n return branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === type)\n .sort((a, b) => compareDesc(a.date!, b.date!))\n .slice(0, limit);\n}\n","import chalk from 'chalk';\n\nconst PREFIX = chalk.gray('│');\n\nexport const logger = {\n header: (title: string) => {\n console.log(`\\n${chalk.bgCyan.black.bold(' GIT-FLOW ')} ${chalk.cyan.bold(title)}`);\n console.log(PREFIX);\n },\n info: (msg: string) => console.log(`${PREFIX} ${chalk.blue('ℹ')} ${msg}`),\n step: (msg: string) => {\n process.stdout.write(`${PREFIX} ${chalk.yellow('➜')} ${msg}`);\n },\n success: (msg: string) => console.log(`${PREFIX} ${chalk.green('✔')} ${msg}`),\n done: () => {\n process.stdout.write(chalk.green(' [OK]\\n'));\n },\n warn: (msg: string) => console.log(`${PREFIX} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${PREFIX} ${chalk.red('✘')} ${msg}`),\n errorRaw: (msg: string) => console.error(`${PREFIX} ${chalk.red(msg)}`),\n dim: (msg: string) => console.log(`${PREFIX} ${chalk.gray(msg)}`),\n dimRaw: (msg: string) => {\n process.stdout.write(`${PREFIX} ${chalk.gray(msg)}`);\n },\n footer: () => console.log(PREFIX + '\\n'),\n};\n","import { confirm } from '@inquirer/prompts';\nimport { \n checkClean, \n fetchRemote, \n getBranches, \n getCurrentBranch, \n checkout, \n merge, \n push,\n pullBranch\n} from '../utils/git.js';\nimport { \n getTargetBranch, \n getLatestRelease, \n getPreviousRelease,\n parseBranch, \n BranchType,\n type BranchInfo\n} from '../utils/branch.js';\nimport { createAction } from './create.js';\nimport { logger } from '../utils/ui.js';\n\n/**\n * 确保目标分支存在,如果不存在则引导用户创建\n */\nasync function ensureTargetBranch(type: BranchType): Promise<BranchInfo> {\n await fetchRemote();\n let branches = await getBranches();\n let target = getTargetBranch(branches, type);\n\n if (!target) {\n logger.warn(`未找到可用的 ${type} 分支(需为今日或未来时间)。`);\n const shouldCreate = await confirm({\n message: `确定要现在创建一个新的 ${type} 分支吗?`,\n default: true\n });\n\n if (shouldCreate) {\n await createAction(type);\n await fetchRemote();\n branches = await getBranches();\n target = getTargetBranch(branches, type);\n }\n }\n\n if (!target) {\n throw new Error(`终止: 未能定位到有效的 ${type} 目标分支。`);\n }\n\n return target;\n}\n\n/**\n * 执行同步逻辑:拉取远程最新代码并同步基准分支\n */\nasync function syncAndPrepare(target: BranchInfo, base: BranchInfo | null) {\n logger.step('正在同步远程代码...');\n await pullBranch(target.name);\n if (base) {\n await pullBranch(base.name);\n }\n logger.done();\n\n if (base && target.name !== base.name) {\n logger.step(`正在同步基准 ${base.name} -> ${target.name}...`);\n await checkout(target.name);\n await merge(target.name, base.name);\n logger.done();\n }\n}\n\nexport async function mergeAction(targetArg?: string) {\n const originalBranch = await getCurrentBranch();\n \n try {\n await checkClean();\n logger.header('合并分支');\n await fetchRemote();\n\n // 1. 语法校验与状态检查\n const currentInfo = parseBranch(originalBranch);\n if (!currentInfo || currentInfo.type !== BranchType.FEATURE) {\n throw new Error('禁止操作:请先切换到 Feature 分支再执行合并。');\n }\n\n const targetType = targetArg === 'dev' ? BranchType.DEV : \n targetArg === 'release' ? BranchType.RELEASE : null;\n \n if (!targetType) {\n throw new Error('错误参数:请指定合并目标 (dev 或 release)。');\n }\n\n logger.info(`当前分支: ${originalBranch}`);\n\n // 2. 定位目标与基准\n const targetBranch = await ensureTargetBranch(targetType);\n const branches = await getBranches();\n const baseBranch = targetType === BranchType.DEV ? getLatestRelease(branches) : getPreviousRelease(branches);\n\n logger.info(`目标环境: ${targetBranch.name}${baseBranch ? ` (基准: ${baseBranch.name})` : ''}`);\n\n // 3. 二次确认 (Release)\n if (targetType === BranchType.RELEASE) {\n const isConfirmed = await confirm({\n message: `⚠️ 确定要将特性分支合并到生产环境 ${targetBranch.name} 吗?`,\n default: false,\n });\n if (!isConfirmed) {\n logger.dim('操作已取消。');\n logger.footer();\n return;\n }\n }\n\n // 4. 同步与合并\n await syncAndPrepare(targetBranch, baseBranch);\n\n logger.step(`正在合并 Feature 到 ${targetBranch.name}...`);\n await checkout(targetBranch.name);\n await merge(targetBranch.name, originalBranch);\n logger.done();\n \n logger.step('正在推送到远程...');\n await push(targetBranch.name);\n logger.done();\n\n // 5. 还原\n await checkout(originalBranch);\n logger.success(`成功!Feature 已合并至 ${targetBranch.name} 并推送到 origin。`);\n logger.dim(`已自动切回 ${originalBranch}`);\n \n logger.footer();\n\n } catch (err: any) {\n logger.errorRaw(err.message);\n const nowBranch = await getCurrentBranch();\n if (nowBranch !== originalBranch) {\n logger.warn(`流程中断,由于代码冲突或其他错误,请手动处理后切回 ${originalBranch}。`);\n }\n logger.footer();\n }\n}\n","import Table from 'cli-table3';\nimport chalk from 'chalk';\nimport { getBranches, fetchRemote } from '../utils/git.js';\nimport { BranchType, getLatestBranches, type BranchInfo } from '../utils/branch.js';\nimport { format } from 'date-fns';\nimport { logger } from '../utils/ui.js';\n\nexport async function listAction(count: string) {\n try {\n await fetchRemote();\n const branches = await getBranches();\n\n const limit = parseInt(count, 10);\n const latestRelease = getLatestBranches(branches, BranchType.RELEASE, limit);\n const latestDev = getLatestBranches(branches, BranchType.DEV, limit);\n\n logger.header(`分支列表 (Latest ${limit})`);\n\n const table = new Table({\n head: [chalk.cyan('Type'), chalk.cyan('Branch Name'), chalk.cyan('Date'), chalk.cyan('Project')],\n style: {\n head: [],\n border: [],\n }\n });\n\n const addRows = (branchInfos: BranchInfo[], typeName: string, color: (s: string) => string) => {\n branchInfos.forEach(info => {\n table.push([\n color(typeName),\n info.name,\n info.date ? format(info.date, 'yyyy-MM-dd') : '-',\n info.project || '-'\n ]);\n });\n };\n\n addRows(latestRelease, 'Release', chalk.green);\n addRows(latestDev, 'Dev', chalk.yellow);\n\n if (table.length === 0) {\n logger.warn('未发现符合规范的 dev 或 release 分支。');\n logger.footer();\n return;\n }\n\n console.log(table.toString());\n logger.footer();\n\n } catch (error: any) {\n logger.errorRaw(`获取分支列表失败: ${error.message}`);\n logger.footer();\n }\n}\n"],"mappings":";AACA,OAAS,WAAAA,MAAe,YCDxB,OAAS,SAAAC,EAAO,UAAAC,MAAc,oBAC9B,OAAS,UAAAC,MAAc,WCDvB,OAAS,aAAAC,MAAiC,aAC1C,OAAOC,MAAW,QAElB,IAAMC,EAAiBF,EAAU,EAEjC,eAAsBG,GAAa,CAEjC,GAAI,EADW,MAAMD,EAAI,OAAO,GACpB,QAAQ,EAClB,MAAM,IAAI,MAAM,iHAAiC,CAErD,CAEA,eAAsBE,GAA+B,CACnD,IAAMC,EAAO,MAAMH,EAAI,UAAU,WAAW,EAC5C,GAAI,CAACG,EAAK,MACR,MAAM,IAAI,MAAM,mHAAwC,EAE1D,OAAOA,EAAK,KACd,CAEA,eAAsBC,GAAc,CAClC,QAAQ,IAAIL,EAAM,KAAK,6EAAiB,CAAC,EACzC,MAAMC,EAAI,MAAM,CAAC,SAAS,CAAC,CAC7B,CAEA,eAAsBK,GAAoC,CAExD,OADmB,MAAML,EAAI,OAAO,GAClB,OACpB,CAEA,eAAsBM,EAASC,EAAgBC,EAAS,GAAOC,EAAqB,CAC9ED,EACEC,EACF,MAAMT,EAAI,SAAS,CAAC,KAAMO,EAAQE,CAAU,CAAC,EAE7C,MAAMT,EAAI,oBAAoBO,CAAM,EAGtC,MAAMP,EAAI,SAASO,CAAM,CAE7B,CAEA,eAAsBG,EAAMC,EAAgBC,EAAgB,CAC1D,GAAI,CACF,MAAMZ,EAAI,MAAM,CAACY,CAAM,CAAC,CAC1B,MAAmB,CACjB,MAAM,IAAI,MAAM,iEAAeA,CAAM,uBAAQD,CAAM;AAAA,qIAA8B,CACnF,CACF,CAEA,eAAsBE,EAAKN,EAAgB,CACzC,MAAMP,EAAI,KAAK,CAAC,KAAM,SAAUO,CAAM,CAAC,CACzC,CAEA,eAAsBO,EAAWP,EAAgB,CAC/C,IAAMQ,EAAW,MAAMf,EAAI,OAAO,EAGlC,GAFgBe,EAAS,IAAI,SAASR,CAAM,EAY1C,QAAQ,IAAIR,EAAM,KAAK,oDAAYQ,CAAM,KAAK,CAAC,EAC/C,MAAMP,EAAI,SAASO,CAAM,EACzB,MAAMP,EAAI,KAAK,SAAUO,CAAM,UAVVQ,EAAS,IAAI,SAAS,kBAAkBR,CAAM,EAAE,EAEnE,QAAQ,IAAIR,EAAM,KAAK,0DAAaQ,CAAM,KAAK,CAAC,EAChD,MAAMP,EAAI,SAAS,CAAC,KAAMO,EAAQ,UAAUA,CAAM,EAAE,CAAC,MAErD,OAAM,IAAI,MAAM,mEAAiBA,CAAM,EAAE,CAO/C,CAEA,eAAsBS,GAAc,CAClC,IAAMC,EAAU,MAAMjB,EAAI,OAAO,CAAC,IAAI,CAAC,EACvC,OAAO,MAAM,KAAK,IAAI,IAAIiB,EAAQ,IAAI,IAAIC,GAAKA,EAAE,QAAQ,kBAAmB,EAAE,CAAC,CAAC,CAAC,CACnF,CC7EA,OAAS,eAAAC,EAAa,cAAAC,EAAY,SAAAC,MAAa,WAQxC,IAAMC,EAAe,aASrB,SAASC,EAAYC,EAAuC,CAEjE,IAAMC,EAAeD,EAAW,MAAM,wBAAwB,EAC9D,GAAIC,EACF,MAAO,CACL,KAAMD,EACN,KAAM,UACN,QAASC,EAAa,CAAC,EACvB,KAAMC,EAAMD,EAAa,CAAC,EAAI,WAAY,IAAI,IAAM,CACtD,EAKF,IAAME,EAAWH,EAAW,MAAM,4BAA4B,EAC9D,GAAIG,EACF,MAAO,CACL,KAAMH,EACN,KAAM,MACN,QAASG,EAAS,CAAC,EACnB,KAAMD,EAAMC,EAAS,CAAC,EAAI,WAAY,IAAI,IAAM,CAClD,EAIF,IAAMC,EAAYJ,EAAW,MAAM,iCAAiC,EACpE,OAAII,EACK,CACL,KAAMJ,EACN,KAAM,UACN,KAAME,EAAME,EAAU,CAAC,EAAI,WAAY,IAAI,IAAM,CACnD,EAGK,IACT,CAEO,SAASC,EAAiBC,EAAuC,CAMtE,OALiBA,EACd,IAAIP,CAAW,EACf,OAAQQ,GAAuBA,GAAG,OAAS,SAAkB,EAC7D,KAAK,CAACC,EAAGD,IAAME,EAAYD,EAAE,KAAOD,EAAE,IAAK,CAAC,EAE/B,CAAC,GAAK,IACxB,CAEO,SAASG,EAAmBJ,EAAuC,CAMxE,OALiBA,EACd,IAAIP,CAAW,EACf,OAAQQ,GAAuBA,GAAG,OAAS,SAAkB,EAC7D,KAAK,CAACC,EAAGD,IAAME,EAAYD,EAAE,KAAOD,EAAE,IAAK,CAAC,EAE/B,CAAC,GAAK,IACxB,CAEO,SAASI,EAAgBL,EAAoBM,EAAqC,CACvF,IAAMC,EAAM,IAAI,KACVC,EAAQ,IAAI,KAAKD,EAAI,YAAY,EAAGA,EAAI,SAAS,EAAGA,EAAI,QAAQ,CAAC,EAQvE,OANgBP,EACb,IAAIP,CAAW,EACf,OAAQQ,GAAuBA,GAAG,OAASK,GAAQ,CAAC,CAACL,EAAE,IAAI,EAC3D,OAAOA,GAAKA,EAAE,MAASO,CAAK,EAC5B,KAAK,CAACN,EAAGD,IAAMQ,EAAWP,EAAE,KAAOD,EAAE,IAAK,CAAC,EAE/B,CAAC,GAAK,IACvB,CACO,SAASS,EAAkBV,EAAoBM,EAAkBK,EAA6B,CACnG,OAAOX,EACJ,IAAIP,CAAW,EACf,OAAQQ,GAAuBA,GAAG,OAASK,CAAI,EAC/C,KAAK,CAACJ,EAAGD,IAAME,EAAYD,EAAE,KAAOD,EAAE,IAAK,CAAC,EAC5C,MAAM,EAAGU,CAAK,CACnB,CC1FA,OAAOC,MAAW,QAElB,IAAMC,EAASD,EAAM,KAAK,QAAG,EAEhBE,EAAS,CACpB,OAASC,GAAkB,CACzB,QAAQ,IAAI;AAAA,EAAKH,EAAM,OAAO,MAAM,KAAK,YAAY,CAAC,IAAIA,EAAM,KAAK,KAAKG,CAAK,CAAC,EAAE,EAClF,QAAQ,IAAIF,CAAM,CACpB,EACA,KAAOG,GAAgB,QAAQ,IAAI,GAAGH,CAAM,IAAID,EAAM,KAAK,QAAG,CAAC,IAAII,CAAG,EAAE,EACxE,KAAOA,GAAgB,CACrB,QAAQ,OAAO,MAAM,GAAGH,CAAM,IAAID,EAAM,OAAO,QAAG,CAAC,IAAII,CAAG,EAAE,CAC9D,EACA,QAAUA,GAAgB,QAAQ,IAAI,GAAGH,CAAM,IAAID,EAAM,MAAM,QAAG,CAAC,IAAII,CAAG,EAAE,EAC5E,KAAM,IAAM,CACV,QAAQ,OAAO,MAAMJ,EAAM,MAAM;AAAA,CAAS,CAAC,CAC7C,EACA,KAAOI,GAAgB,QAAQ,IAAI,GAAGH,CAAM,IAAID,EAAM,OAAO,QAAG,CAAC,IAAII,CAAG,EAAE,EAC1E,MAAQA,GAAgB,QAAQ,MAAM,GAAGH,CAAM,IAAID,EAAM,IAAI,QAAG,CAAC,IAAII,CAAG,EAAE,EAC1E,SAAWA,GAAgB,QAAQ,MAAM,GAAGH,CAAM,IAAID,EAAM,IAAII,CAAG,CAAC,EAAE,EACtE,IAAMA,GAAgB,QAAQ,IAAI,GAAGH,CAAM,IAAID,EAAM,KAAKI,CAAG,CAAC,EAAE,EAChE,OAASA,GAAgB,CACvB,QAAQ,OAAO,MAAM,GAAGH,CAAM,IAAID,EAAM,KAAKI,CAAG,CAAC,EAAE,CACrD,EACA,OAAQ,IAAM,QAAQ,IAAIH,EAAS;AAAA,CAAI,CACzC,EHCA,eAAeI,EAAgBC,EAAgD,CAC7E,IAAMC,EAAiB,MAAMC,EAAiB,EACxCC,EAAW,MAAMC,EAAY,EAC7BC,EAAgBC,EAAiBH,CAAQ,EACzCI,EAAaF,GAAe,MAAQJ,EAE1CO,EAAO,KAAK,6BAASP,CAAc,EAAE,EACjCI,EACFG,EAAO,KAAK,6BAASH,EAAc,IAAI,EAAE,EAEzCG,EAAO,KAAK,qGAA0B,EAGxC,IAAMC,EAAOT,GAAc,MAAMU,EAAO,CACtC,QAAS,sEACT,QAAS,CACP,CAAE,KAAM,qCAAkB,eAA0B,EACpD,CAAE,KAAM,iCAAc,WAAsB,EAC5C,CAAE,KAAM,qCAAkB,eAA0B,CACtD,CACF,CAAC,EAEKC,EAAUN,GAAe,SAAW,OACpCO,EAAQC,EAAO,IAAI,KAAQ,UAAU,EAErCC,EAAY,MAAMC,EAAM,CAC5B,QAAS,yEAA4BH,CAAK,KAC1C,QAASA,EACT,SAAWI,GACJ,UAAU,KAAKA,CAAK,EACrBA,EAAQJ,EAAc,oHAA0BA,CAAK,IAClD,GAF4B,oFAIvC,CAAC,EAEGK,EACJ,OAAIR,IAAS,YACXQ,EAAQ,MAAMF,EAAM,CAClB,QAAS,qEACT,SAAWA,GAAUG,EAAa,KAAKH,CAAK,GAAK,iIACnD,CAAC,GAGI,CAAE,KAAAN,EAAM,WAAAF,EAAY,QAAAI,EAAS,KAAMG,EAAW,MAAAG,CAAM,CAC7D,CAEA,eAAsBE,EAAaC,EAAwB,CAEzD,IAAMpB,EAAa,OAAOoB,GAAQ,SAAWA,EAAoB,OACjE,GAAI,CACFZ,EAAO,OAAO,0BAAM,EACpB,MAAMa,EAAW,EACjB,MAAMC,EAAY,EAElB,IAAMrB,EAAiB,MAAMC,EAAiB,EACxCqB,EAAS,MAAMxB,EAAgBC,CAAU,EACzC,CAAE,KAAAS,EAAM,WAAAF,EAAY,QAAAI,EAAS,KAAAa,EAAM,MAAAP,CAAM,EAAIM,EAE/CE,EACAhB,IAAS,UAEXgB,EAAa,QADA,MAAMC,EAAY,CACN,IAAIF,CAAI,IAAIP,CAAK,GAE1CQ,EAAa,GAAGd,CAAO,IAAIF,CAAI,IAAIe,CAAI,GAGzChB,EAAO,KAAK,sBAAOD,CAAU,iBAAOkB,CAAU,KAAK,EACnD,MAAME,EAASF,EAAY,GAAMlB,CAAU,EAEvCE,IAAS,WACX,MAAMmB,EAAKH,CAAU,EAEvBjB,EAAO,KAAK,EAERC,IAAS,UACXD,EAAO,QAAQ,sFAAgB,GAE/BA,EAAO,QAAQ,gFAAe,EAG1BP,IAAoB,MAAMC,EAAiB,IAC7CM,EAAO,OAAO,8CAAWP,CAAc,KAAK,EAC5C,MAAM0B,EAAS1B,CAAc,EAC7BO,EAAO,KAAK,IAIhBA,EAAO,OAAO,CAEhB,OAASqB,EAAU,CACjBrB,EAAO,SAASqB,EAAI,OAAO,EAC3BrB,EAAO,OAAO,CAChB,CACF,CIvHA,OAAS,WAAAsB,MAAe,oBAyBxB,eAAeC,EAAmBC,EAAuC,CACvE,MAAMC,EAAY,EAClB,IAAIC,EAAW,MAAMC,EAAY,EAC7BC,EAASC,EAAgBH,EAAUF,CAAI,EAiB3C,GAfKI,IACHE,EAAO,KAAK,wCAAUN,CAAI,uFAAiB,EACtB,MAAMO,EAAQ,CACjC,QAAS,sEAAeP,CAAI,4BAC5B,QAAS,EACX,CAAC,IAGC,MAAMQ,EAAaR,CAAI,EACvB,MAAMC,EAAY,EAClBC,EAAW,MAAMC,EAAY,EAC7BC,EAASC,EAAgBH,EAAUF,CAAI,IAIvC,CAACI,EACH,MAAM,IAAI,MAAM,kEAAgBJ,CAAI,iCAAQ,EAG9C,OAAOI,CACT,CAKA,eAAeK,EAAeL,EAAoBM,EAAyB,CACzEJ,EAAO,KAAK,qDAAa,EACzB,MAAMK,EAAWP,EAAO,IAAI,EACxBM,GACF,MAAMC,EAAWD,EAAK,IAAI,EAE5BJ,EAAO,KAAK,EAERI,GAAQN,EAAO,OAASM,EAAK,OAC/BJ,EAAO,KAAK,wCAAUI,EAAK,IAAI,OAAON,EAAO,IAAI,KAAK,EACtD,MAAMQ,EAASR,EAAO,IAAI,EAC1B,MAAMS,EAAMT,EAAO,KAAMM,EAAK,IAAI,EAClCJ,EAAO,KAAK,EAEhB,CAEA,eAAsBQ,EAAYC,EAAoB,CACpD,IAAMC,EAAiB,MAAMC,EAAiB,EAE9C,GAAI,CACF,MAAMC,EAAW,EACjBZ,EAAO,OAAO,0BAAM,EACpB,MAAML,EAAY,EAGlB,IAAMkB,EAAcC,EAAYJ,CAAc,EAC9C,GAAI,CAACG,GAAeA,EAAY,OAAS,UACvC,MAAM,IAAI,MAAM,uHAA6B,EAG/C,IAAME,EAAaN,IAAc,YAChBA,IAAc,oBAAiC,KAEhE,GAAI,CAACM,EACH,MAAM,IAAI,MAAM,qGAA+B,EAGjDf,EAAO,KAAK,6BAASU,CAAc,EAAE,EAGrC,IAAMM,EAAe,MAAMvB,EAAmBsB,CAAU,EAClDnB,EAAW,MAAMC,EAAY,EAC7BoB,EAAaF,IAAe,MAAiBG,EAAiBtB,CAAQ,EAAIuB,EAAmBvB,CAAQ,EAK3G,GAHAI,EAAO,KAAK,6BAASgB,EAAa,IAAI,GAAGC,EAAa,mBAASA,EAAW,IAAI,IAAM,EAAE,EAAE,EAGpFF,IAAe,WAKb,CAJgB,MAAMd,EAAQ,CAChC,QAAS,2GAAsBe,EAAa,IAAI,gBAChD,QAAS,EACX,CAAC,EACiB,CAChBhB,EAAO,IAAI,sCAAQ,EACnBA,EAAO,OAAO,EACd,MACF,CAIF,MAAMG,EAAea,EAAcC,CAAU,EAE7CjB,EAAO,KAAK,2CAAkBgB,EAAa,IAAI,KAAK,EACpD,MAAMV,EAASU,EAAa,IAAI,EAChC,MAAMT,EAAMS,EAAa,KAAMN,CAAc,EAC7CV,EAAO,KAAK,EAEZA,EAAO,KAAK,+CAAY,EACxB,MAAMoB,EAAKJ,EAAa,IAAI,EAC5BhB,EAAO,KAAK,EAGZ,MAAMM,EAASI,CAAc,EAC7BV,EAAO,QAAQ,sDAAmBgB,EAAa,IAAI,wCAAe,EAClEhB,EAAO,IAAI,kCAASU,CAAc,EAAE,EAEpCV,EAAO,OAAO,CAEhB,OAASqB,EAAU,CACjBrB,EAAO,SAASqB,EAAI,OAAO,EACT,MAAMV,EAAiB,IACvBD,GAChBV,EAAO,KAAK,0JAA6BU,CAAc,QAAG,EAE5DV,EAAO,OAAO,CAChB,CACF,CC7IA,OAAOsB,MAAW,aAClB,OAAOC,MAAW,QAGlB,OAAS,UAAAC,MAAc,WAGvB,eAAsBC,EAAWC,EAAe,CAC9C,GAAI,CACF,MAAMC,EAAY,EAClB,IAAMC,EAAW,MAAMC,EAAY,EAE7BC,EAAQ,SAASJ,EAAO,EAAE,EAC1BK,EAAgBC,EAAkBJ,YAA8BE,CAAK,EACrEG,EAAYD,EAAkBJ,QAA0BE,CAAK,EAEnEI,EAAO,OAAO,oCAAgBJ,CAAK,GAAG,EAEtC,IAAMK,EAAQ,IAAIC,EAAM,CACtB,KAAM,CAACC,EAAM,KAAK,MAAM,EAAGA,EAAM,KAAK,aAAa,EAAGA,EAAM,KAAK,MAAM,EAAGA,EAAM,KAAK,SAAS,CAAC,EAC/F,MAAO,CACL,KAAM,CAAC,EACP,OAAQ,CAAC,CACX,CACF,CAAC,EAEKC,EAAU,CAACC,EAA2BC,EAAkBC,IAAiC,CAC7FF,EAAY,QAAQG,GAAQ,CAC1BP,EAAM,KAAK,CACTM,EAAMD,CAAQ,EACdE,EAAK,KACLA,EAAK,KAAOC,EAAOD,EAAK,KAAM,YAAY,EAAI,IAC9CA,EAAK,SAAW,GAClB,CAAC,CACH,CAAC,CACH,EAKA,GAHAJ,EAAQP,EAAe,UAAWM,EAAM,KAAK,EAC7CC,EAAQL,EAAW,MAAOI,EAAM,MAAM,EAElCF,EAAM,SAAW,EAAG,CACtBD,EAAO,KAAK,wFAA4B,EACxCA,EAAO,OAAO,EACd,MACF,CAEA,QAAQ,IAAIC,EAAM,SAAS,CAAC,EAC5BD,EAAO,OAAO,CAEhB,OAASU,EAAY,CACnBV,EAAO,SAAS,qDAAaU,EAAM,OAAO,EAAE,EAC5CV,EAAO,OAAO,CAChB,CACF,CN/CA,IAAMW,EAAU,IAAIC,EAEpBD,EACG,KAAK,KAAK,EACV,YAAY,iFAAoC,EAChD,QAAQ,OAAO,EAElBA,EACG,QAAQ,QAAQ,EAChB,YAAY,wDAA+B,EAC3C,OAAOE,CAAY,EAEtBF,EACG,QAAQ,OAAO,EACf,YAAY,oDAAsB,EAClC,SAAS,WAAY,+CAAsB,EAC3C,OAAOG,CAAW,EAErBH,EACG,QAAQ,MAAM,EACd,YAAY,gEAAwB,EACpC,SAAS,UAAW,8DAAkB,GAAG,EACzC,OAAOI,CAAU,EAEpBJ,EAAQ,MAAM","names":["Command","input","select","format","simpleGit","chalk","git","checkClean","getUserName","name","fetchRemote","getCurrentBranch","checkout","branch","create","startPoint","merge","target","source","push","pullBranch","branches","getBranches","summary","b","compareDesc","compareAsc","parse","REQ_NO_REGEX","parseBranch","branchName","releaseMatch","parse","devMatch","featMatch","getLatestRelease","branches","b","a","compareDesc","getPreviousRelease","getTargetBranch","type","now","today","compareAsc","getLatestBranches","limit","chalk","PREFIX","logger","title","msg","getCreateConfig","forcedType","originalBranch","getCurrentBranch","branches","getBranches","latestRelease","getLatestRelease","baseBranch","logger","type","select","project","today","format","dateInput","input","value","reqNo","REQ_NO_REGEX","createAction","arg","checkClean","fetchRemote","config","date","branchName","getUserName","checkout","push","err","confirm","ensureTargetBranch","type","fetchRemote","branches","getBranches","target","getTargetBranch","logger","confirm","createAction","syncAndPrepare","base","pullBranch","checkout","merge","mergeAction","targetArg","originalBranch","getCurrentBranch","checkClean","currentInfo","parseBranch","targetType","targetBranch","baseBranch","getLatestRelease","getPreviousRelease","push","err","Table","chalk","format","listAction","count","fetchRemote","branches","getBranches","limit","latestRelease","getLatestBranches","latestDev","logger","table","Table","chalk","addRows","branchInfos","typeName","color","info","format","error","program","Command","createAction","mergeAction","listAction"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/utils/git.ts","../src/utils/branch.ts","../src/utils/ui.ts","../src/commands/merge.ts","../src/commands/list.ts","../src/commands/sync.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander'\nimport { createRequire } from 'module'\nimport { createAction } from './commands/create.js'\nimport { mergeAction } from './commands/merge.js'\nimport { listAction } from './commands/list.js'\nimport { syncAction } from './commands/sync.js'\n\n// todo: optimize json import\nconst require = createRequire(import.meta.url)\nconst { version } = require('../package.json')\n\nconst program = new Command()\n\nprogram\n .name('agf')\n .description('Auto Git Flow CLI - 自动化 Git 分支管理工具')\n .version(version)\n\nprogram\n .command('create')\n .description('创建新分支 (Release, Dev, Feature)')\n .action(createAction)\n\nprogram\n .command('merge')\n .description('合并分支 (Safe-Merge 策略)')\n .argument('<target>', '目标环境 (dev 或 release)')\n .action(mergeAction)\n\nprogram\n .command('list')\n .description('查看最新的 dev 和 release 分支')\n .argument('[count]', '列出的分支个数 (默认 2)', '2')\n .action(listAction)\n\nprogram\n .command('sync')\n .description('同步基准分支到当前 Feature 分支')\n .action(syncAction)\n\nprogram.parse()\n","import { input, select } from '@inquirer/prompts'\nimport { format } from 'date-fns'\nimport {\n checkClean,\n fetchRemote,\n getBranches,\n getUserName,\n checkout,\n push,\n getCurrentBranch,\n} from '../utils/git.js'\nimport { getLatestRelease, REQ_NO_REGEX, BranchType } from '../utils/branch.js'\nimport { logger } from '../utils/ui.js'\n\ninterface CreateConfig {\n type: BranchType\n baseBranch: string\n project: string\n date: string\n reqNo?: string | undefined\n}\n\nasync function getCreateConfig(forcedType?: BranchType): Promise<CreateConfig> {\n const originalBranch = await getCurrentBranch()\n const branches = await getBranches()\n const latestRelease = getLatestRelease(branches)\n const baseBranch = latestRelease?.name || originalBranch\n\n logger.info(`当前分支: ${originalBranch}`)\n if (latestRelease) {\n logger.info(`基准分支: ${latestRelease.name}`)\n } else {\n // TODO: Is this logic correctly ?\n logger.warn('未找到 Release 分支,将以当前分支为基准')\n }\n\n const type =\n forcedType ||\n (await select({\n message: '请选择要创建的分支类型:',\n choices: [\n { name: 'Feature (特性开发)', value: BranchType.FEATURE },\n { name: 'Dev (测试环境)', value: BranchType.DEV },\n { name: 'Release (生产环境)', value: BranchType.RELEASE },\n ],\n }))\n\n const today = format(new Date(), 'yyyyMMdd')\n\n const dateInput = await input({\n message: `请输入日期 (格式: YYYYMMDD, 默认: ${today}):`,\n default: today,\n validate: (value) => {\n if (!/^\\d{8}$/.test(value)) return '❌ 格式错误: 请输入8位数字日期'\n if (value < today)\n return `❌ 日期过早: 日期必须大于或等于当前日期 (${today})`\n return true\n },\n })\n\n let project = latestRelease?.project || ''\n if (type !== BranchType.FEATURE && !project) {\n project = await input({\n message: '请输入项目名称:',\n validate: (v) => (v.trim() ? true : '❌ 项目名称不能为空'),\n })\n }\n\n let reqNo\n if (type === BranchType.FEATURE) {\n reqNo = await input({\n message: '请输入需求编号 (例如 QZ-8848):',\n validate: (input) =>\n REQ_NO_REGEX.test(input) ||\n '❌ 格式错误: 需求编号必须为 QZ 后接4-8位数字 (如 QZ-8848)',\n })\n }\n\n return { type, baseBranch, project, date: dateInput, reqNo }\n}\n\nexport async function createAction(arg?: BranchType | any) {\n // Commander passes the Command object if no args are defined, so we need to filter that out\n const forcedType = typeof arg === 'string' ? (arg as BranchType) : undefined\n try {\n logger.header('创建分支')\n await checkClean()\n await fetchRemote()\n\n const originalBranch = await getCurrentBranch()\n const config = await getCreateConfig(forcedType)\n const { type, baseBranch, project, date, reqNo } = config\n\n let branchName: string\n if (type === BranchType.FEATURE) {\n const user = await getUserName()\n branchName = `feat/${user}-${date}-${reqNo}`\n } else {\n branchName = `${project}-${type}-${date}`\n }\n\n logger.step(`正在从 ${baseBranch} 创建 ${branchName}...`)\n await checkout(branchName, true, baseBranch)\n await push(branchName)\n logger.done()\n\n if (type === BranchType.FEATURE) {\n logger.success(\n `分支 ${branchName} 创建成功并已推送到远程,已切换至该分支`\n )\n } else {\n logger.success(`分支 ${branchName} 创建成功并已推送到远程`)\n // 非特性分支创建后切回原分支\n if (originalBranch !== (await getCurrentBranch())) {\n logger.dimRaw(`正在切回原分支 ${originalBranch}...`)\n await checkout(originalBranch)\n logger.done()\n }\n }\n\n logger.footer()\n } catch (err: any) {\n logger.errorRaw(err.message)\n logger.footer()\n }\n}\n","import { simpleGit, type SimpleGit } from 'simple-git'\nimport chalk from 'chalk'\n\nlet _git: SimpleGit | null = null\n\nexport function getGit() {\n if (!_git) {\n _git = simpleGit()\n }\n return _git\n}\n\nexport function resetGitInstance() {\n _git = null\n}\n\nexport async function checkClean() {\n const status = await getGit().status()\n if (!status.isClean()) {\n throw new Error('❌ 工作区有未提交的代码,请先 Commit 或 Stash。')\n }\n}\n\nexport async function getUserName(): Promise<string> {\n const name = await getGit().getConfig('user.name')\n if (!name.value) {\n throw new Error('❌ 获取不到用户名,请执行 git config user.name 配置。')\n }\n return name.value\n}\n\nexport async function fetchRemote() {\n console.log(chalk.gray('正在拉取远程最新分支列表...'))\n await getGit().fetch(['--prune'])\n}\n\nexport async function getCurrentBranch(): Promise<string> {\n const branchInfo = await getGit().branch()\n // TODO: Why this occur empty string ?\n return branchInfo.current\n}\n\nexport async function checkout(\n branch: string,\n create = false,\n startPoint?: string\n) {\n if (create) {\n if (startPoint) {\n // 始终使用远程分支作为基准\n const branches = await getGit().branch()\n const remoteRef = `remotes/origin/${startPoint}`\n const remoteExists = branches.all.includes(remoteRef)\n\n if (!remoteExists) {\n throw new Error(`❌ 错误: 远程分支 origin/${startPoint} 不存在`)\n }\n\n // https://git-scm.com/docs/git-config#Documentation/git-config.txt-branchautoSetupMerge\n // Use --no-track to prevent auto track\n await getGit().checkout([\n '-b',\n branch,\n '--no-track',\n `origin/${startPoint}`,\n ])\n } else {\n await getGit().checkoutLocalBranch(branch)\n }\n } else {\n await getGit().checkout(branch)\n }\n}\n\nexport async function merge(target: string, source: string) {\n try {\n await getGit().merge([source])\n } catch (err: any) {\n console.error(err)\n throw new Error(\n `⚠️ 发生代码冲突!从 ${source} 合并到 ${target} 失败。\\n请手动解决冲突文件并提交,然后切换回原分支。`\n )\n }\n}\n\nexport async function push(branch: string) {\n await getGit().push(['-u', 'origin', branch])\n}\n\nexport async function pullBranch(branch: string) {\n const branches = await getGit().branch()\n const isLocal = branches.all.includes(branch)\n\n if (!isLocal) {\n // Check if remote exists\n const remoteExists = branches.all.includes(`remotes/origin/${branch}`)\n if (remoteExists) {\n console.log(chalk.gray(`正在从远程拉取分支 ${branch}...`))\n await getGit().checkout(['-b', branch, `origin/${branch}`])\n } else {\n throw new Error(`❌ 错误: 远程不存在分支 ${branch}`)\n }\n } else {\n console.log(chalk.gray(`正在更新本地分支 ${branch}...`))\n await getGit().checkout(branch)\n await getGit().pull('origin', branch)\n }\n}\n\nexport async function getBranches() {\n const summary = await getGit().branch(['-a'])\n return Array.from(\n new Set(summary.all.map((b) => b.replace('remotes/origin/', '')))\n )\n}\n\n/**\n * 检查分支 A 是否落后于分支 B\n * @returns true 表示 A 落后于 B(B 有 A 没有的提交)\n */\nexport async function isBranchBehind(\n branchA: string,\n branchB: string\n): Promise<boolean> {\n // 使用远程分支进行比对\n const refA = `origin/${branchA}`\n const refB = `origin/${branchB}`\n\n const result = await getGit().raw(['rev-list', '--count', `${refA}..${refB}`])\n return parseInt(result.trim(), 10) > 0\n}\n","import { compareDesc, compareAsc, parse } from 'date-fns'\n\nexport enum BranchType {\n RELEASE = 'RELEASE',\n DEV = 'DEV',\n FEATURE = 'FEATURE',\n}\n\nexport const REQ_NO_REGEX = /^QZ-\\d{4,8}$/\n\nexport interface BranchInfo {\n name: string\n type: BranchType\n date?: Date\n project?: string\n}\n\nexport function parseBranch(branchName: string): BranchInfo | null {\n // Release: {project}-RELEASE-{YYYYMMDD}\n const releaseMatch = branchName.match(/^(.+)-RELEASE-(\\d{8})$/)\n if (releaseMatch) {\n return {\n name: branchName,\n type: BranchType.RELEASE,\n project: releaseMatch[1]!,\n date: parse(releaseMatch[2]!, 'yyyyMMdd', new Date()),\n }\n }\n\n // Dev: {project}-DEV-{YYYYMMDD}\n // {project}-dev-{YYYYMMDD}\n const devMatch = branchName.match(/^(.+)-(?:DEV|dev)-(\\d{8})$/)\n if (devMatch) {\n return {\n name: branchName,\n type: BranchType.DEV,\n project: devMatch[1]!,\n date: parse(devMatch[2]!, 'yyyyMMdd', new Date()),\n }\n }\n\n // Feature: feat/{user}-{date}-{reqNo}\n const featMatch = branchName.match(/^feat\\/(.+)-(\\d{8})-(QZ-\\d{4})$/)\n if (featMatch) {\n return {\n name: branchName,\n type: BranchType.FEATURE,\n date: parse(featMatch[2]!, 'yyyyMMdd', new Date()),\n }\n }\n\n return null\n}\n\nexport function getLatestRelease(branches: string[]): BranchInfo | null {\n const releases = branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === BranchType.RELEASE)\n .sort((a, b) => compareDesc(a.date!, b.date!))\n\n return releases[0] || null\n}\n\nexport function getPreviousRelease(branches: string[]): BranchInfo | null {\n const releases = branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === BranchType.RELEASE)\n .sort((a, b) => compareDesc(a.date!, b.date!))\n\n return releases[1] || null\n}\n\nexport function getTargetBranch(\n branches: string[],\n type: BranchType\n): BranchInfo | null {\n const now = new Date()\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()) // Start of today\n\n const targets = branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === type && !!b.date)\n .filter((b) => b.date! >= today) // Only today or future\n .sort((a, b) => compareAsc(a.date!, b.date!))\n\n return targets[0] || null // Return the earliest one (which is the closest to today)\n}\nexport function getLatestBranches(\n branches: string[],\n type: BranchType,\n limit: number\n): BranchInfo[] {\n return branches\n .map(parseBranch)\n .filter((b): b is BranchInfo => b?.type === type)\n .sort((a, b) => compareDesc(a.date!, b.date!))\n .slice(0, limit)\n}\n","import chalk from 'chalk'\n\nconst PREFIX = chalk.gray('│')\n\nexport const logger = {\n header: (title: string) => {\n console.log(\n `\\n${chalk.bgCyan.black.bold(' GIT-FLOW ')} ${chalk.cyan.bold(title)}`\n )\n console.log(PREFIX)\n },\n info: (msg: string) => console.log(`${PREFIX} ${chalk.blue('ℹ')} ${msg}`),\n step: (msg: string) => {\n process.stdout.write(`${PREFIX} ${chalk.yellow('➜')} ${msg}`)\n },\n success: (msg: string) => console.log(`${PREFIX} ${chalk.green('✔')} ${msg}`),\n done: () => {\n process.stdout.write(chalk.green(' [OK]\\n'))\n },\n warn: (msg: string) => console.log(`${PREFIX} ${chalk.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${PREFIX} ${chalk.red('✘')} ${msg}`),\n errorRaw: (msg: string) => console.error(`${PREFIX} ${chalk.red(msg)}`),\n dim: (msg: string) => console.log(`${PREFIX} ${chalk.gray(msg)}`),\n dimRaw: (msg: string) => {\n process.stdout.write(`${PREFIX} ${chalk.gray(msg)}`)\n },\n footer: () => console.log(PREFIX + '\\n'),\n}\n","import { confirm } from '@inquirer/prompts'\nimport {\n checkClean,\n fetchRemote,\n getBranches,\n getCurrentBranch,\n checkout,\n merge,\n push,\n pullBranch,\n isBranchBehind,\n} from '../utils/git.js'\nimport {\n getTargetBranch,\n getLatestRelease,\n getPreviousRelease,\n parseBranch,\n BranchType,\n type BranchInfo,\n} from '../utils/branch.js'\nimport { createAction } from './create.js'\nimport { logger } from '../utils/ui.js'\n\n/**\n * 确保目标分支存在,如果不存在则引导用户创建\n */\nasync function ensureTargetBranch(type: BranchType): Promise<BranchInfo> {\n await fetchRemote()\n let branches = await getBranches()\n let target = getTargetBranch(branches, type)\n\n if (!target) {\n logger.warn(`未找到可用的 ${type} 分支(需为今日或未来时间)。`)\n const shouldCreate = await confirm({\n message: `确定要现在创建一个新的 ${type} 分支吗?`,\n default: true,\n })\n\n if (shouldCreate) {\n await createAction(type)\n await fetchRemote()\n branches = await getBranches()\n target = getTargetBranch(branches, type)\n }\n }\n\n if (!target) {\n throw new Error(`终止: 未能定位到有效的 ${type} 目标分支。`)\n }\n\n return target\n}\n\n/**\n * 执行同步逻辑:拉取远程最新代码并按需同步基准分支\n */\nasync function syncAndPrepare(\n target: BranchInfo,\n base: BranchInfo | null,\n feature: string\n) {\n logger.step('正在同步远程代码...')\n await pullBranch(target.name)\n if (base) {\n await pullBranch(base.name)\n await pullBranch(feature)\n }\n logger.done()\n\n if (base) {\n // 1. 检查目标分支是否落后于基准分支\n if (await isBranchBehind(target.name, base.name)) {\n logger.step(`正在同步基准 ${base.name} -> ${target.name}...`)\n await checkout(target.name)\n await merge(target.name, base.name)\n await push(target.name)\n logger.done()\n } else {\n logger.dim(`${target.name} 已包含 ${base.name} 的所有提交,跳过同步`)\n }\n\n // 2. 检查特性分支是否落后于基准分支\n if (await isBranchBehind(feature, base.name)) {\n logger.step(`检测到 ${feature} 落后于 ${base.name},正在同步...`)\n await checkout(feature)\n await merge(feature, base.name)\n await push(feature)\n logger.done()\n }\n }\n}\n\nexport async function mergeAction(targetArg?: string) {\n const originalBranch = await getCurrentBranch()\n\n try {\n await checkClean()\n logger.header('合并分支')\n await fetchRemote()\n\n // 1. 语法校验与状态检查\n const currentInfo = parseBranch(originalBranch)\n if (!currentInfo || currentInfo.type !== BranchType.FEATURE) {\n throw new Error('禁止操作:请先切换到 Feature 分支再执行合并。')\n }\n\n const targetType =\n targetArg === 'dev'\n ? BranchType.DEV\n : targetArg === 'release'\n ? BranchType.RELEASE\n : null\n\n if (!targetType) {\n throw new Error('错误参数:请指定合并目标 (dev 或 release)。')\n }\n\n logger.info(`当前分支: ${originalBranch}`)\n\n // 2. 定位目标与基准\n const targetBranch = await ensureTargetBranch(targetType)\n const branches = await getBranches()\n const baseBranch =\n targetType === BranchType.DEV\n ? getLatestRelease(branches)\n : getPreviousRelease(branches)\n\n logger.info(\n `目标环境: ${targetBranch.name}${baseBranch ? ` (基准: ${baseBranch.name})` : ''}`\n )\n\n // 3. 二次确认 (Release)\n if (targetType === BranchType.RELEASE) {\n const isConfirmed = await confirm({\n message: `⚠️ 确定要将特性分支合并到生产环境 ${targetBranch.name} 吗?`,\n default: false,\n })\n if (!isConfirmed) {\n logger.dim('操作已取消。')\n logger.footer()\n return\n }\n }\n\n // 4. 同步与合并\n await syncAndPrepare(targetBranch, baseBranch, originalBranch)\n\n logger.step(`正在合并 Feature 到 ${targetBranch.name}...`)\n await checkout(targetBranch.name)\n await merge(targetBranch.name, originalBranch)\n logger.done()\n\n logger.step('正在推送到远程...')\n await push(targetBranch.name)\n logger.done()\n\n // 5. 还原\n await checkout(originalBranch)\n logger.success(\n `成功!Feature 已合并至 ${targetBranch.name} 并推送到 origin。`\n )\n logger.dim(`已自动切回 ${originalBranch}`)\n\n logger.footer()\n } catch (err: any) {\n logger.errorRaw(err.message)\n const nowBranch = await getCurrentBranch()\n if (nowBranch !== originalBranch) {\n logger.warn(\n `流程中断,由于代码冲突或其他错误,请手动处理后切回 ${originalBranch}。`\n )\n }\n logger.footer()\n }\n}\n","import Table from 'cli-table3'\nimport chalk from 'chalk'\nimport { getBranches, fetchRemote } from '../utils/git.js'\nimport {\n BranchType,\n getLatestBranches,\n type BranchInfo,\n} from '../utils/branch.js'\nimport { format } from 'date-fns'\nimport { logger } from '../utils/ui.js'\n\nexport async function listAction(count: string) {\n try {\n await fetchRemote()\n const branches = await getBranches()\n\n const limit = parseInt(count, 10)\n const latestRelease = getLatestBranches(branches, BranchType.RELEASE, limit)\n const latestDev = getLatestBranches(branches, BranchType.DEV, limit)\n\n logger.header(`分支列表 (Latest ${limit})`)\n\n const table = new Table({\n head: [\n chalk.cyan('Type'),\n chalk.cyan('Branch Name'),\n chalk.cyan('Date'),\n chalk.cyan('Project'),\n ],\n style: {\n head: [],\n border: [],\n },\n })\n\n const addRows = (\n branchInfos: BranchInfo[],\n typeName: string,\n color: (s: string) => string\n ) => {\n branchInfos.forEach((info) => {\n table.push([\n color(typeName),\n info.name,\n info.date ? format(info.date, 'yyyy-MM-dd') : '-',\n info.project || '-',\n ])\n })\n }\n\n addRows(latestRelease, 'Release', chalk.green)\n addRows(latestDev, 'Dev', chalk.yellow)\n\n if (table.length === 0) {\n logger.warn('未发现符合规范的 dev 或 release 分支。')\n logger.footer()\n return\n }\n\n console.log(table.toString())\n logger.footer()\n } catch (error: any) {\n logger.errorRaw(`获取分支列表失败: ${error.message}`)\n logger.footer()\n }\n}\n","import {\n checkClean,\n fetchRemote,\n getBranches,\n getCurrentBranch,\n checkout,\n merge,\n push,\n pullBranch,\n isBranchBehind,\n} from '../utils/git.js'\nimport { getLatestRelease, parseBranch, BranchType } from '../utils/branch.js'\nimport { logger } from '../utils/ui.js'\n\nexport async function syncAction() {\n const currentBranch = await getCurrentBranch()\n\n try {\n await checkClean()\n logger.header('同步基准分支')\n await fetchRemote()\n\n const currentInfo = parseBranch(currentBranch)\n if (!currentInfo || currentInfo.type !== BranchType.FEATURE) {\n throw new Error('禁止操作:请先切换到 Feature 分支再执行同步。')\n }\n\n logger.info(`当前分支: ${currentBranch}`)\n\n const branches = await getBranches()\n const baseBranch = getLatestRelease(branches)\n\n if (!baseBranch) {\n throw new Error('未找到可用的 Release 基准分支。')\n }\n\n logger.info(`基准分支: ${baseBranch.name}`)\n\n logger.step('正在拉取远程代码...')\n await pullBranch(baseBranch.name)\n await pullBranch(currentBranch)\n logger.done()\n\n const isBehind = await isBranchBehind(currentBranch, baseBranch.name)\n\n if (!isBehind) {\n logger.success(\n `当前分支 ${currentBranch} 已包含 ${baseBranch.name} 的所有提交,无需同步。`\n )\n logger.footer()\n return\n }\n\n logger.step(`正在合并 ${baseBranch.name} -> ${currentBranch}...`)\n await checkout(currentBranch)\n await merge(currentBranch, baseBranch.name)\n logger.done()\n\n logger.step('正在推送到远程...')\n await push(currentBranch)\n logger.done()\n\n logger.success(\n `成功!${baseBranch.name} 已合并至 ${currentBranch} 并推送到 origin。`\n )\n logger.footer()\n } catch (err: any) {\n logger.errorRaw(err.message)\n const nowBranch = await getCurrentBranch()\n if (nowBranch !== currentBranch) {\n logger.warn(\n `流程中断,由于代码冲突或其他错误,请手动处理后切回 ${currentBranch}。`\n )\n }\n logger.footer()\n }\n}\n"],"mappings":"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","names":["Command","createRequire","input","select","format","simpleGit","chalk","_git","getGit","checkClean","getGit","getUserName","name","fetchRemote","chalk","getCurrentBranch","checkout","branch","create","startPoint","branches","remoteRef","merge","target","source","err","push","pullBranch","getBranches","summary","b","isBranchBehind","branchA","branchB","refA","refB","result","compareDesc","compareAsc","parse","REQ_NO_REGEX","parseBranch","branchName","releaseMatch","parse","devMatch","featMatch","getLatestRelease","branches","b","a","compareDesc","getPreviousRelease","getTargetBranch","type","now","today","compareAsc","getLatestBranches","limit","chalk","PREFIX","logger","title","msg","getCreateConfig","forcedType","originalBranch","getCurrentBranch","branches","getBranches","latestRelease","getLatestRelease","baseBranch","logger","type","select","today","format","dateInput","input","value","project","v","reqNo","REQ_NO_REGEX","createAction","arg","checkClean","fetchRemote","config","date","branchName","getUserName","checkout","push","err","confirm","ensureTargetBranch","type","fetchRemote","branches","getBranches","target","getTargetBranch","logger","confirm","createAction","syncAndPrepare","base","feature","pullBranch","isBranchBehind","checkout","merge","push","mergeAction","targetArg","originalBranch","getCurrentBranch","checkClean","currentInfo","parseBranch","targetType","targetBranch","baseBranch","getLatestRelease","getPreviousRelease","err","Table","chalk","format","listAction","count","fetchRemote","branches","getBranches","limit","latestRelease","getLatestBranches","latestDev","logger","table","Table","chalk","addRows","branchInfos","typeName","color","info","format","error","syncAction","currentBranch","getCurrentBranch","checkClean","logger","fetchRemote","currentInfo","parseBranch","branches","getBranches","baseBranch","getLatestRelease","pullBranch","isBranchBehind","checkout","merge","push","err","require","createRequire","version","program","Command","createAction","mergeAction","listAction","syncAction"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sppk/auto-git-flow",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,21 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"dev": "tsx src/index.ts",
|
|
15
15
|
"build": "tsup",
|
|
16
|
-
"prepublishOnly": "pnpm build"
|
|
16
|
+
"prepublishOnly": "pnpm build",
|
|
17
|
+
"prepare": "husky",
|
|
18
|
+
"lint": "eslint .",
|
|
19
|
+
"lint:fix": "eslint . --fix",
|
|
20
|
+
"format": "prettier --write .",
|
|
21
|
+
"format:check": "prettier --check ."
|
|
22
|
+
},
|
|
23
|
+
"lint-staged": {
|
|
24
|
+
"*.{ts,js}": [
|
|
25
|
+
"eslint --fix",
|
|
26
|
+
"prettier --write"
|
|
27
|
+
],
|
|
28
|
+
"*.json": [
|
|
29
|
+
"prettier --write"
|
|
30
|
+
]
|
|
17
31
|
},
|
|
18
32
|
"publishConfig": {
|
|
19
33
|
"access": "public",
|
|
@@ -24,10 +38,20 @@
|
|
|
24
38
|
"license": "ISC",
|
|
25
39
|
"packageManager": "pnpm@10.8.0",
|
|
26
40
|
"devDependencies": {
|
|
41
|
+
"@commitlint/cli": "^20.3.0",
|
|
42
|
+
"@commitlint/config-conventional": "^20.3.0",
|
|
43
|
+
"@eslint/js": "^9.39.2",
|
|
27
44
|
"@types/node": "^25.0.3",
|
|
45
|
+
"eslint": "^9.39.2",
|
|
46
|
+
"eslint-config-prettier": "^10.1.8",
|
|
47
|
+
"husky": "^9.1.7",
|
|
48
|
+
"lint-staged": "^16.2.7",
|
|
49
|
+
"prettier": "^3.7.4",
|
|
28
50
|
"tsup": "^8.5.1",
|
|
29
51
|
"tsx": "^4.21.0",
|
|
30
|
-
"typescript": "^5.9.3"
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
|
+
"typescript-eslint": "^8.52.0",
|
|
54
|
+
"vitest": "^4.0.16"
|
|
31
55
|
},
|
|
32
56
|
"dependencies": {
|
|
33
57
|
"@inquirer/prompts": "^8.1.0",
|