gflows 0.1.13 → 0.1.15
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 +256 -269
- package/package.json +6 -2
- package/src/cli.ts +51 -28
- package/src/commands/bump.ts +81 -31
- package/src/commands/completion.ts +21 -30
- package/src/commands/delete.ts +10 -30
- package/src/commands/finish.ts +34 -58
- package/src/commands/help.ts +2 -1
- package/src/commands/init.ts +8 -13
- package/src/commands/list.ts +7 -24
- package/src/commands/start.ts +15 -18
- package/src/commands/status.ts +11 -28
- package/src/commands/switch.ts +149 -52
- package/src/config.ts +43 -23
- package/src/constants.ts +1 -1
- package/src/errors.ts +4 -2
- package/src/git.ts +187 -28
- package/src/index.ts +59 -63
- package/src/out.ts +10 -2
- package/src/types.ts +3 -7
package/README.md
CHANGED
|
@@ -8,16 +8,31 @@ A lightweight CLI for consistent Git branching workflows: long-lived **main** (p
|
|
|
8
8
|
|
|
9
9
|
## Table of contents
|
|
10
10
|
|
|
11
|
+
**Get started**
|
|
12
|
+
|
|
11
13
|
- [Prerequisites](#prerequisites)
|
|
12
14
|
- [Installation](#installation)
|
|
13
|
-
- [Concepts](#concepts)
|
|
14
15
|
- [Quick start](#quick-start)
|
|
15
|
-
|
|
16
|
+
|
|
17
|
+
**Understand**
|
|
18
|
+
|
|
19
|
+
- [Concepts](#concepts)
|
|
20
|
+
- [Flowcharts](#flowcharts)
|
|
16
21
|
- [Branch types in detail](#branch-types-in-detail)
|
|
22
|
+
|
|
23
|
+
**Reference**
|
|
24
|
+
|
|
25
|
+
- [Command reference](#command-reference)
|
|
26
|
+
|
|
27
|
+
**Configure & operate**
|
|
28
|
+
|
|
17
29
|
- [Configuration](#configuration)
|
|
18
30
|
- [Scripting and CI](#scripting-and-ci)
|
|
19
31
|
- [Exit codes](#exit-codes)
|
|
20
32
|
- [Troubleshooting](#troubleshooting)
|
|
33
|
+
|
|
34
|
+
**More**
|
|
35
|
+
|
|
21
36
|
- [Shell completion](#shell-completion)
|
|
22
37
|
- [Publishing (maintainers)](#publishing-maintainers)
|
|
23
38
|
- [License](#license)
|
|
@@ -26,8 +41,8 @@ A lightweight CLI for consistent Git branching workflows: long-lived **main** (p
|
|
|
26
41
|
|
|
27
42
|
## Prerequisites
|
|
28
43
|
|
|
29
|
-
- **Bun** ≥ 1.0 (recommended). The CLI runs TypeScript directly
|
|
30
|
-
- **Git** for
|
|
44
|
+
- **Bun** ≥ 1.0 (recommended). The CLI runs TypeScript directly.
|
|
45
|
+
- **Git** for repository operations.
|
|
31
46
|
|
|
32
47
|
Check versions:
|
|
33
48
|
|
|
@@ -40,120 +55,204 @@ git --version
|
|
|
40
55
|
|
|
41
56
|
## Installation
|
|
42
57
|
|
|
43
|
-
**
|
|
58
|
+
**Dev dependency (recommended):** `bun add --dev gflows` or `npm install --save-dev gflows`.
|
|
59
|
+
**JSR:** `npx jsr add --dev @alialnaghmoush/gflows` or `deno add --dev jsr:@alialnaghmoush/gflows`.
|
|
44
60
|
|
|
45
|
-
|
|
61
|
+
Run with `bunx gflows ...` or `npx gflows ...`. [npm](https://www.npmjs.com/package/gflows) · [JSR](https://jsr.io/@alialnaghmoush/gflows)
|
|
46
62
|
|
|
47
|
-
|
|
48
|
-
npm install --save-dev gflows
|
|
49
|
-
```
|
|
63
|
+
**Global:** `bun add --global gflows` or `npm install --global gflows`
|
|
50
64
|
|
|
51
|
-
|
|
65
|
+
---
|
|
52
66
|
|
|
53
|
-
|
|
54
|
-
bun add --dev gflows
|
|
55
|
-
```
|
|
67
|
+
## Quick start
|
|
56
68
|
|
|
57
|
-
**
|
|
69
|
+
**1. One-time setup** — In your repo, ensure `main` exists and create `dev`:
|
|
58
70
|
|
|
59
71
|
```bash
|
|
60
|
-
|
|
72
|
+
bun gflows init
|
|
61
73
|
```
|
|
62
74
|
|
|
63
|
-
|
|
75
|
+
Use `--no-push` to skip push, `--dry-run` to preview. Pass `--main`, `--dev`, `--remote` to persist to `.gflows.json`.
|
|
64
76
|
|
|
65
77
|
```bash
|
|
66
|
-
|
|
78
|
+
bun gflows init --main main --dev develop --remote origin
|
|
67
79
|
```
|
|
68
80
|
|
|
69
|
-
**
|
|
81
|
+
**2. Daily development** (feature → dev):
|
|
70
82
|
|
|
71
83
|
```bash
|
|
72
|
-
|
|
84
|
+
bun gflows start feature add-login
|
|
85
|
+
# ... code, commit ...
|
|
86
|
+
bun gflows finish feature
|
|
87
|
+
bun gflows finish feature --push
|
|
88
|
+
bun gflows finish feature --push -D
|
|
73
89
|
```
|
|
74
90
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
- [npm: gflows](https://www.npmjs.com/package/gflows)
|
|
78
|
-
- [JSR: @alialnaghmoush/gflows](https://jsr.io/@alialnaghmoush/gflows)
|
|
79
|
-
|
|
80
|
-
If installed as a local dev dependency, run via your package runner:
|
|
81
|
-
|
|
82
|
-
- Bun: `bunx gflows ...` (or `bun gflows ...` when available in your Bun setup)
|
|
83
|
-
- npm: `npx gflows ...`
|
|
84
|
-
|
|
85
|
-
**Global install (optional):**
|
|
86
|
-
|
|
87
|
-
**npm**
|
|
91
|
+
**3. Release** (dev → main, then tag):
|
|
88
92
|
|
|
89
93
|
```bash
|
|
90
|
-
|
|
94
|
+
bun gflows bump up minor
|
|
95
|
+
bun gflows start release v1.3.0
|
|
96
|
+
# ... update CHANGELOG, commit ...
|
|
97
|
+
bun gflows finish release --push
|
|
91
98
|
```
|
|
92
99
|
|
|
93
|
-
**
|
|
100
|
+
**4. Hotfix** (main → fix → main + dev):
|
|
94
101
|
|
|
95
102
|
```bash
|
|
96
|
-
bun
|
|
103
|
+
bun gflows start hotfix v1.3.1
|
|
104
|
+
# ... fix, commit ...
|
|
105
|
+
bun gflows finish hotfix --push
|
|
97
106
|
```
|
|
98
107
|
|
|
99
108
|
---
|
|
100
109
|
|
|
101
110
|
## Concepts
|
|
102
111
|
|
|
103
|
-
- **main** —
|
|
104
|
-
- **dev** —
|
|
105
|
-
- **Workflow branches** — Short-lived branches with a type prefix
|
|
106
|
-
- **Merge targets
|
|
107
|
-
- **feature / chore / spike** → `dev` only.
|
|
108
|
-
- **bugfix** → `dev` (or `main` if the bugfix was started from main with `-o main`).
|
|
109
|
-
- **release** → `main` first, then `main` is merged into `dev`; a tag is created.
|
|
110
|
-
- **hotfix** → `main` first, then `main` is merged into `dev`; a tag is created.
|
|
112
|
+
- **main** — Production branch. Only release and hotfix merge here.
|
|
113
|
+
- **dev** — Integration branch. Feature, bugfix, chore, spike merge here. Created by `gflows init` from main.
|
|
114
|
+
- **Workflow branches** — Short-lived branches with a type prefix; each has a base and merge target(s). No history rewriting.
|
|
115
|
+
- **Merge targets:** feature/chore/spike → dev; bugfix → dev (or main with `-o main`); release/hotfix → main then dev + tag.
|
|
111
116
|
|
|
112
|
-
|
|
117
|
+
Override names and prefixes via [configuration](#configuration).
|
|
113
118
|
|
|
114
119
|
---
|
|
115
120
|
|
|
116
|
-
##
|
|
121
|
+
## Flowcharts
|
|
117
122
|
|
|
118
|
-
|
|
123
|
+
### Lifecycle (init → start → finish)
|
|
119
124
|
|
|
120
|
-
```
|
|
121
|
-
|
|
125
|
+
```mermaid
|
|
126
|
+
flowchart LR
|
|
127
|
+
subgraph setup["One-time setup"]
|
|
128
|
+
A[main exists] --> B["bun gflows init"]
|
|
129
|
+
B --> C[dev created]
|
|
130
|
+
C --> D[optional: push dev]
|
|
131
|
+
end
|
|
132
|
+
subgraph daily["Daily workflow"]
|
|
133
|
+
E["bun gflows start<br/>type name"] --> F[work & commit]
|
|
134
|
+
F --> G["bun gflows finish<br/>type"]
|
|
135
|
+
G --> H{type?}
|
|
136
|
+
H -->|feature/bugfix/chore/spike| I[merged to dev]
|
|
137
|
+
H -->|release/hotfix| J[merged to main → dev + tag]
|
|
138
|
+
end
|
|
139
|
+
setup --> daily
|
|
122
140
|
```
|
|
123
141
|
|
|
124
|
-
|
|
142
|
+
### init
|
|
125
143
|
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
gflows init
|
|
144
|
+
```mermaid
|
|
145
|
+
flowchart TD
|
|
146
|
+
Start([bun gflows init]) --> Repo{In git repo?}
|
|
147
|
+
Repo -->|no| ErrRepo[Exit: Not a repo]
|
|
148
|
+
Repo -->|yes| MainExists{main branch exists?}
|
|
149
|
+
MainExists -->|no| ErrMain[Exit: Create main first]
|
|
150
|
+
MainExists -->|yes| DevExists{dev branch exists?}
|
|
151
|
+
DevExists -->|yes| DoneNoOp[Done: nothing to do]
|
|
152
|
+
DevExists -->|no| CreateDev[Create dev from main]
|
|
153
|
+
CreateDev --> Push{--no-push?}
|
|
154
|
+
Push -->|no| DoPush[Push dev to remote]
|
|
155
|
+
Push -->|yes| SkipPush[Skip push]
|
|
156
|
+
DoPush --> Done[Done]
|
|
157
|
+
SkipPush --> Done
|
|
158
|
+
DoneNoOp --> Done
|
|
129
159
|
```
|
|
130
160
|
|
|
131
|
-
|
|
161
|
+
### start
|
|
132
162
|
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
163
|
+
```mermaid
|
|
164
|
+
flowchart TD
|
|
165
|
+
Start([bun gflows start type name]) --> Repo{In git repo?}
|
|
166
|
+
Repo -->|no| ErrRepo[Exit: Not a repo]
|
|
167
|
+
Repo -->|yes| Clean{Tree clean or --force?}
|
|
168
|
+
Clean -->|no| ErrDirty[Exit: Uncommitted changes]
|
|
169
|
+
Clean -->|yes| Base[Resolve base branch for type]
|
|
170
|
+
Base --> BaseExists{Base exists locally or remote?}
|
|
171
|
+
BaseExists -->|no| ErrBase[Exit: Base not found]
|
|
172
|
+
BaseExists -->|yes| Create[Create workflow branch from base]
|
|
173
|
+
Create --> PushOpt{--push?}
|
|
174
|
+
PushOpt -->|yes| Push[Push new branch to remote]
|
|
175
|
+
PushOpt -->|no| Done[Done]
|
|
176
|
+
Push --> Done
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### finish (merge targets by branch type)
|
|
180
|
+
|
|
181
|
+
```mermaid
|
|
182
|
+
flowchart TD
|
|
183
|
+
Start([bun gflows finish type]) --> Resolve[Resolve branch to finish]
|
|
184
|
+
Resolve --> T{type}
|
|
185
|
+
T -->|feature / chore / spike| M1[Merge → dev]
|
|
186
|
+
T -->|bugfix from dev| M1
|
|
187
|
+
T -->|bugfix from main| M2[Merge → main]
|
|
188
|
+
T -->|release| M3[Merge → main]
|
|
189
|
+
M3 --> M3b[Merge main → dev]
|
|
190
|
+
M3b --> Tag1[Create tag]
|
|
191
|
+
T -->|hotfix| M4[Merge → main]
|
|
192
|
+
M4 --> M4b[Merge main → dev]
|
|
193
|
+
M4b --> Tag2[Create tag]
|
|
194
|
+
M2 --> M2b[Merge main → dev]
|
|
195
|
+
M1 --> Opt[Optional: delete branch, push]
|
|
196
|
+
M2b --> Opt
|
|
197
|
+
Tag1 --> Opt
|
|
198
|
+
Tag2 --> Opt
|
|
199
|
+
Opt --> Done([Done])
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Branch types and merge targets
|
|
203
|
+
|
|
204
|
+
```mermaid
|
|
205
|
+
flowchart TB
|
|
206
|
+
subgraph longlived["Long-lived branches"]
|
|
207
|
+
main[main]
|
|
208
|
+
dev[dev]
|
|
209
|
+
end
|
|
210
|
+
subgraph workflow["Workflow branches"]
|
|
211
|
+
feature[feature/...]
|
|
212
|
+
bugfix[bugfix/...]
|
|
213
|
+
chore[chore/...]
|
|
214
|
+
release[release/...]
|
|
215
|
+
hotfix[hotfix/...]
|
|
216
|
+
spike[spike/...]
|
|
217
|
+
end
|
|
218
|
+
feature --> dev
|
|
219
|
+
chore --> dev
|
|
220
|
+
spike --> dev
|
|
221
|
+
bugfix --> dev
|
|
222
|
+
bugfix -.->|"-o main"| main
|
|
223
|
+
release --> main
|
|
224
|
+
main --> dev
|
|
225
|
+
release -.-> dev
|
|
226
|
+
hotfix --> main
|
|
227
|
+
main --> dev
|
|
228
|
+
hotfix -.-> dev
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### bump (version)
|
|
232
|
+
|
|
233
|
+
```mermaid
|
|
234
|
+
flowchart LR
|
|
235
|
+
Start([bun gflows bump direction type]) --> Discover[Discover package.json, jsr.json]
|
|
236
|
+
Discover --> Read[Read version from primary root]
|
|
237
|
+
Read --> Calc[Compute new version]
|
|
238
|
+
Calc --> Write[Write to all roots]
|
|
239
|
+
Write --> Done([Done])
|
|
139
240
|
```
|
|
140
241
|
|
|
141
|
-
|
|
242
|
+
---
|
|
142
243
|
|
|
143
|
-
|
|
144
|
-
gflows bump up minor # e.g. 1.2.3 → 1.3.0
|
|
145
|
-
gflows start release v1.3.0
|
|
146
|
-
# ... update CHANGELOG, commit ...
|
|
147
|
-
gflows finish release --push # merge to main, then dev; tag v1.3.0; push
|
|
148
|
-
```
|
|
244
|
+
## Branch types in detail
|
|
149
245
|
|
|
150
|
-
|
|
246
|
+
| Type | Short | Base (default) | With `-o main` | Merge target(s) | Tag |
|
|
247
|
+
| ------- | ----- | -------------- | -------------- | -------------------------- | --- |
|
|
248
|
+
| feature | `-f` | dev | — | dev | no |
|
|
249
|
+
| bugfix | `-b` | dev | main | dev (or main if from main) | no |
|
|
250
|
+
| chore | `-c` | dev | — | dev | no |
|
|
251
|
+
| release | `-r` | dev | — | main, then dev | yes |
|
|
252
|
+
| hotfix | `-x` | main | — | main, then dev | yes |
|
|
253
|
+
| spike | `-e` | dev | — | dev | no |
|
|
151
254
|
|
|
152
|
-
|
|
153
|
-
gflows start hotfix v1.3.1
|
|
154
|
-
# ... fix, commit ...
|
|
155
|
-
gflows finish hotfix --push # merge to main, then dev; tag v1.3.1; push
|
|
156
|
-
```
|
|
255
|
+
Release and hotfix names must be a version (`vX.Y.Z` or `X.Y.Z`). Branch names use default prefixes (e.g. `feature/add-login`); override in [configuration](#configuration). Invalid names (e.g. `..`, `*`, spaces) → exit 1.
|
|
157
256
|
|
|
158
257
|
---
|
|
159
258
|
|
|
@@ -161,13 +260,12 @@ gflows finish hotfix --push # merge to main, then dev; tag v1.3.1;
|
|
|
161
260
|
|
|
162
261
|
### Summary table
|
|
163
262
|
|
|
164
|
-
|
|
165
263
|
| Command | Short | Description |
|
|
166
264
|
| ------------ | ----- | ------------------------------------------------------------------------- |
|
|
167
265
|
| `init` | `-I` | Ensure main exists; create dev from main. |
|
|
168
266
|
| `start` | `-S` | Create a workflow branch (requires type + name). |
|
|
169
267
|
| `finish` | `-F` | Merge branch into target(s), optional tag (release/hotfix), delete, push. |
|
|
170
|
-
| `switch` | `-W` | Switch to a workflow branch (picker or name)
|
|
268
|
+
| `switch` | `-W` | Switch to a workflow branch (picker or name); with uncommitted changes: prompt or `--move` / `--restore` / `--clean` / `--cancel`. |
|
|
171
269
|
| `delete` | `-L` | Delete local workflow branch(es). Never main/dev. |
|
|
172
270
|
| `list` | `-l` | List workflow branches; optional type filter and remote. |
|
|
173
271
|
| `bump` | — | Bump or rollback package version (patch/minor/major). |
|
|
@@ -177,9 +275,7 @@ gflows finish hotfix --push # merge to main, then dev; tag v1.3.1;
|
|
|
177
275
|
| `version` | `-V` | Show version. |
|
|
178
276
|
|
|
179
277
|
|
|
180
|
-
**
|
|
181
|
-
|
|
182
|
-
**Common flags** (used by multiple commands):
|
|
278
|
+
**Common flags:**
|
|
183
279
|
|
|
184
280
|
|
|
185
281
|
| Flag | Short | Description |
|
|
@@ -202,18 +298,14 @@ gflows finish hotfix --push # merge to main, then dev; tag v1.3.1;
|
|
|
202
298
|
|
|
203
299
|
### init
|
|
204
300
|
|
|
205
|
-
Ensures
|
|
206
|
-
|
|
207
|
-
You can set and persist config with `**--main`**, `**--dev`**, and `**-R`/`--remote**`. Any of these flags cause init to write or update `.gflows.json` with the given values (after a successful init; skipped with `--dry-run`).
|
|
301
|
+
Ensures main exists; creates dev from main if missing. Use `--main`, `--dev`, `-R` to persist to `.gflows.json`.
|
|
208
302
|
|
|
209
303
|
**Examples:**
|
|
210
304
|
|
|
211
305
|
```bash
|
|
212
|
-
gflows init
|
|
213
|
-
gflows init --
|
|
214
|
-
gflows init
|
|
215
|
-
gflows init -C ../other-repo # run in another directory
|
|
216
|
-
gflows init --dry-run # log intended actions only
|
|
306
|
+
bun gflows init
|
|
307
|
+
bun gflows init --main main --dev develop --remote origin
|
|
308
|
+
bun gflows init -C ../other-repo --dry-run
|
|
217
309
|
```
|
|
218
310
|
|
|
219
311
|
**Flags:**
|
|
@@ -221,7 +313,7 @@ gflows init --dry-run # log intended actions only
|
|
|
221
313
|
|
|
222
314
|
| Flag | Short | Description |
|
|
223
315
|
| ----------------- | ----- | ------------------------------------------------------------- |
|
|
224
|
-
| `--push` | `-p` | Push dev to remote after creating.
|
|
316
|
+
| `--push` | `-p` | Push dev to remote after creating (default). |
|
|
225
317
|
| `--main <name>` | — | Main branch name (persisted to `.gflows.json` when provided). |
|
|
226
318
|
| `--dev <name>` | — | Dev branch name (persisted to `.gflows.json` when provided). |
|
|
227
319
|
| `--remote <name>` | `-R` | Remote name (persisted to `.gflows.json` when provided). |
|
|
@@ -235,21 +327,16 @@ gflows init --dry-run # log intended actions only
|
|
|
235
327
|
|
|
236
328
|
### start
|
|
237
329
|
|
|
238
|
-
Creates a
|
|
239
|
-
|
|
240
|
-
**Pre-checks:** Repository is Git; not detached HEAD; no rebase/merge in progress; working tree clean (unless `--force`); base branch exists (local or after fetch).
|
|
330
|
+
Creates a workflow branch from the correct base. Requires type + name; release/hotfix name must be a version. Pre-checks: git repo, clean tree (or `--force`), base exists.
|
|
241
331
|
|
|
242
332
|
**Examples:**
|
|
243
333
|
|
|
244
334
|
```bash
|
|
245
|
-
gflows start feature auth-refactor
|
|
246
|
-
gflows start
|
|
247
|
-
gflows start
|
|
248
|
-
gflows start
|
|
249
|
-
gflows start
|
|
250
|
-
gflows start feature wip --force # allow uncommitted changes
|
|
251
|
-
gflows start feature api-v2 --push # create branch and push to remote
|
|
252
|
-
gflows start chore deps-update -C ./backend # run in subdirectory
|
|
335
|
+
bun gflows start feature auth-refactor
|
|
336
|
+
bun gflows start bugfix fix-login --from main
|
|
337
|
+
bun gflows start release v2.0.0
|
|
338
|
+
bun gflows start hotfix 1.2.1
|
|
339
|
+
bun gflows start feature wip --force --push
|
|
253
340
|
```
|
|
254
341
|
|
|
255
342
|
**Flags:**
|
|
@@ -271,25 +358,17 @@ gflows start chore deps-update -C ./backend # run in subdirectory
|
|
|
271
358
|
|
|
272
359
|
### finish
|
|
273
360
|
|
|
274
|
-
Merges the
|
|
275
|
-
|
|
276
|
-
**Pre-checks:** Not detached HEAD; no rebase/merge in progress; current branch (or `-B` target) is not main or dev; for release/hotfix, tag does not already exist.
|
|
361
|
+
Merges the branch (current or `-B`) into its target(s). Release/hotfix: merge to main, then main → dev, create tag. Use `--no-ff` for a merge commit. On conflict, resolve then `git merge --continue` or re-run finish.
|
|
277
362
|
|
|
278
363
|
**Examples:**
|
|
279
364
|
|
|
280
365
|
```bash
|
|
281
|
-
gflows finish feature
|
|
282
|
-
gflows finish feature -B feature/auth
|
|
283
|
-
gflows finish
|
|
284
|
-
gflows finish
|
|
285
|
-
gflows finish release --push # merge to main, then dev; tag; push
|
|
286
|
-
gflows finish hotfix -s # sign the tag (GPG)
|
|
287
|
-
gflows finish hotfix -T # no tag (e.g. abandon hotfix as release)
|
|
288
|
-
gflows finish -y # skip "Delete branch after finish?" prompt (use default)
|
|
366
|
+
bun gflows finish feature
|
|
367
|
+
bun gflows finish feature -B feature/auth --push -D
|
|
368
|
+
bun gflows finish release --push
|
|
369
|
+
bun gflows finish hotfix -s -T -y
|
|
289
370
|
```
|
|
290
371
|
|
|
291
|
-
**Branch resolution:** If you omit the branch name, gflows uses the current branch. With `-B` and no value in a TTY, it shows a picker of workflow branches. Without a TTY, you must pass the branch name explicitly.
|
|
292
|
-
|
|
293
372
|
**Flags:**
|
|
294
373
|
|
|
295
374
|
|
|
@@ -316,38 +395,56 @@ gflows finish -y # skip "Delete branch after finish?"
|
|
|
316
395
|
|
|
317
396
|
### switch
|
|
318
397
|
|
|
319
|
-
|
|
398
|
+
Switch to a workflow branch. With TTY and no branch name, shows a picker; otherwise pass the branch name (e.g. `gflows switch dev` or `-B dev`).
|
|
399
|
+
|
|
400
|
+
**Uncommitted changes:** If the working tree is dirty and stdin is a TTY, you are prompted to choose:
|
|
401
|
+
|
|
402
|
+
| Option | Description |
|
|
403
|
+
| ------ | ----------- |
|
|
404
|
+
| **Cancel** | Abort switching. |
|
|
405
|
+
| **Move changes to target** | Take current changes with you to the target branch (stash → switch → pop). |
|
|
406
|
+
| **Restore** | Save changes for the current branch; switch; restore any saved changes for the target branch (if any). |
|
|
407
|
+
| **Clean** | Discard changes and switch to the target branch clean at HEAD. |
|
|
408
|
+
|
|
409
|
+
You can skip the prompt by passing exactly one of the flags below. If the target branch has saved changes and you use **Clean**, a warning is shown (unless `-q`).
|
|
320
410
|
|
|
321
411
|
**Examples:**
|
|
322
412
|
|
|
323
413
|
```bash
|
|
324
|
-
gflows switch
|
|
325
|
-
gflows switch feature/auth-refactor
|
|
326
|
-
gflows
|
|
414
|
+
bun gflows switch
|
|
415
|
+
bun gflows switch feature/auth-refactor
|
|
416
|
+
bun gflows switch dev --restore
|
|
417
|
+
bun gflows switch main --clean
|
|
418
|
+
bun gflows -W feature/auth-refactor
|
|
327
419
|
```
|
|
328
420
|
|
|
329
421
|
**Flags:**
|
|
330
422
|
|
|
331
423
|
|
|
332
|
-
| Flag | Short | Description
|
|
333
|
-
| -------------- | ----- |
|
|
334
|
-
| `--path <dir>` | `-C` | Run as if in `<dir>`.
|
|
335
|
-
| `--
|
|
336
|
-
| `--
|
|
424
|
+
| Flag | Short | Description |
|
|
425
|
+
| -------------- | ----- | --------------------------------------------------------------------------- |
|
|
426
|
+
| `--path <dir>` | `-C` | Run as if in `<dir>`. |
|
|
427
|
+
| `--branch <name>` | `-B` | Branch to switch to (alternative to positional). |
|
|
428
|
+
| `--move` | — | Take current changes to the target branch; no prompt. |
|
|
429
|
+
| `--restore` | — | Per-branch save/restore; no prompt. |
|
|
430
|
+
| `--clean` | — | Discard changes and switch clean; no prompt. |
|
|
431
|
+
| `--cancel` | — | Abort switching; no prompt. |
|
|
432
|
+
| `--verbose` | `-v` | Verbose output. |
|
|
433
|
+
| `--quiet` | `-q` | Minimal output (suppresses Clean warning about saved changes on target). |
|
|
337
434
|
|
|
338
435
|
|
|
339
436
|
---
|
|
340
437
|
|
|
341
438
|
### delete
|
|
342
439
|
|
|
343
|
-
|
|
440
|
+
Delete local workflow branch(es). Never deletes main/dev. TTY: picker; otherwise pass branch name(s).
|
|
344
441
|
|
|
345
442
|
**Examples:**
|
|
346
443
|
|
|
347
444
|
```bash
|
|
348
|
-
gflows delete
|
|
349
|
-
gflows delete feature/old-spike
|
|
350
|
-
gflows delete feature/one feature/two
|
|
445
|
+
bun gflows delete
|
|
446
|
+
bun gflows delete feature/old-spike
|
|
447
|
+
bun gflows delete feature/one feature/two
|
|
351
448
|
```
|
|
352
449
|
|
|
353
450
|
**Flags:**
|
|
@@ -364,16 +461,14 @@ gflows delete feature/one feature/two # delete multiple
|
|
|
364
461
|
|
|
365
462
|
### list
|
|
366
463
|
|
|
367
|
-
|
|
464
|
+
List workflow branches (one per line). Filter by type; use `-r` to include remote (may run `git fetch`).
|
|
368
465
|
|
|
369
466
|
**Examples:**
|
|
370
467
|
|
|
371
468
|
```bash
|
|
372
|
-
gflows list
|
|
373
|
-
gflows list feature
|
|
374
|
-
gflows list -r
|
|
375
|
-
gflows list -r feature # remote + local feature branches
|
|
376
|
-
gflows list --include-remote
|
|
469
|
+
bun gflows list
|
|
470
|
+
bun gflows list feature
|
|
471
|
+
bun gflows list -r
|
|
377
472
|
```
|
|
378
473
|
|
|
379
474
|
**Flags:**
|
|
@@ -392,20 +487,14 @@ gflows list --include-remote
|
|
|
392
487
|
|
|
393
488
|
### bump
|
|
394
489
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
**Positionals:** direction `up` | `down`, type `patch` | `minor` | `major`. When both are omitted and stdin is a TTY, shows interactive selects. When not a TTY, both are required.
|
|
490
|
+
Bump or rollback version in `package.json` and `jsr.json` (monorepo: all discovered roots). No git operations. Direction: `up`|`down`; type: `patch`|`minor`|`major`. TTY: interactive; non-TTY: both required.
|
|
398
491
|
|
|
399
492
|
**Examples:**
|
|
400
493
|
|
|
401
494
|
```bash
|
|
402
|
-
gflows bump up patch
|
|
403
|
-
gflows bump
|
|
404
|
-
gflows bump
|
|
405
|
-
gflows bump down patch # 1.2.4 → 1.2.3 (floor at 0)
|
|
406
|
-
gflows bump down minor # 1.3.0 → 1.2.0
|
|
407
|
-
gflows bump # interactive (direction + type) when TTY
|
|
408
|
-
gflows bump --dry-run # print old → new, no file writes
|
|
495
|
+
bun gflows bump up patch
|
|
496
|
+
bun gflows bump down minor
|
|
497
|
+
bun gflows bump --dry-run
|
|
409
498
|
```
|
|
410
499
|
|
|
411
500
|
**Flags:**
|
|
@@ -423,13 +512,13 @@ gflows bump --dry-run # print old → new, no file writes
|
|
|
423
512
|
|
|
424
513
|
### status
|
|
425
514
|
|
|
426
|
-
Shows current branch,
|
|
515
|
+
Shows current branch, type, base, merge target(s), ahead/behind. Read-only.
|
|
427
516
|
|
|
428
517
|
**Examples:**
|
|
429
518
|
|
|
430
519
|
```bash
|
|
431
|
-
gflows status
|
|
432
|
-
gflows -t
|
|
520
|
+
bun gflows status
|
|
521
|
+
bun gflows -t
|
|
433
522
|
```
|
|
434
523
|
|
|
435
524
|
**Flags:**
|
|
@@ -446,58 +535,17 @@ gflows -t
|
|
|
446
535
|
|
|
447
536
|
### completion
|
|
448
537
|
|
|
449
|
-
Prints
|
|
450
|
-
|
|
451
|
-
**Examples:** See [Shell completion](#shell-completion).
|
|
452
|
-
|
|
453
|
-
---
|
|
538
|
+
Prints completion script for bash/zsh/fish. See [Shell completion](#shell-completion).
|
|
454
539
|
|
|
455
540
|
### help & version
|
|
456
541
|
|
|
457
|
-
|
|
458
|
-
gflows help
|
|
459
|
-
gflows -h
|
|
460
|
-
gflows version
|
|
461
|
-
gflows -V
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
---
|
|
465
|
-
|
|
466
|
-
## Branch types in detail
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
| Type | Short | Base (default) | With `-o main` | Merge target(s) | Tag |
|
|
470
|
-
| ------- | ----- | -------------- | -------------- | -------------------------- | --- |
|
|
471
|
-
| feature | `-f` | dev | — | dev | no |
|
|
472
|
-
| bugfix | `-b` | dev | main | dev (or main if from main) | no |
|
|
473
|
-
| chore | `-c` | dev | — | dev | no |
|
|
474
|
-
| release | `-r` | dev | — | main, then dev | yes |
|
|
475
|
-
| hotfix | `-x` | main | — | main, then dev | yes |
|
|
476
|
-
| spike | `-e` | dev | — | dev | no |
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
- **feature** — New functionality; branches from dev, merges to dev.
|
|
480
|
-
- **bugfix** — Bug fixes. Usually from dev → dev. Use `-o main` when fixing a bug on production (branch from main, merge to main then dev).
|
|
481
|
-
- **chore** — Tasks that don’t change behavior (deps, tooling, docs). dev → dev.
|
|
482
|
-
- **release** — Prepare a release from dev: merge to main, then merge main into dev, create tag (e.g. `v1.2.0`). Name must be a version: `vX.Y.Z` or `X.Y.Z`.
|
|
483
|
-
- **hotfix** — Urgent fix from production (main). Merge to main, then main into dev; tag. Name must be a version.
|
|
484
|
-
- **spike** — Short-lived experiment; dev → dev, no tag. Discard or merge as needed.
|
|
485
|
-
|
|
486
|
-
**Naming:** Branch names use prefixes by default: `feature/add-login`, `bugfix/fix-login`, `release/v1.0.0`, `hotfix/v1.0.1`, `chore/update-deps`, `spike/try-cache`. Prefixes can be overridden in [configuration](#configuration). Invalid branch names (e.g. containing `..`, `*`, spaces) are rejected with exit code 1.
|
|
542
|
+
`bun gflows help` · `bun gflows -V`
|
|
487
543
|
|
|
488
544
|
---
|
|
489
545
|
|
|
490
546
|
## Configuration
|
|
491
547
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
**Resolution order** (later overrides earlier):
|
|
495
|
-
|
|
496
|
-
1. Built-in defaults (`main`, `dev`, `origin`, and default prefixes).
|
|
497
|
-
2. Repo config file: `**.gflows.json`** in repo root, or `**gflows`** key in `**package.json`**.
|
|
498
|
-
3. CLI (e.g. `--main`, `--dev`, `-R`/`--remote`).
|
|
499
|
-
|
|
500
|
-
Only include keys you want to override; the rest stay default. Invalid or malformed config is ignored (with an optional warning when using `-v`).
|
|
548
|
+
Optional. Override main, dev, remote, prefixes. Resolution: defaults → `.gflows.json` or `package.json` "gflows" key → CLI flags. Invalid config is ignored (`-v` for warning).
|
|
501
549
|
|
|
502
550
|
### Example: `.gflows.json` (full)
|
|
503
551
|
|
|
@@ -517,92 +565,40 @@ Only include keys you want to override; the rest stay default. Invalid or malfor
|
|
|
517
565
|
}
|
|
518
566
|
```
|
|
519
567
|
|
|
520
|
-
### Example: minimal
|
|
568
|
+
### Example: minimal
|
|
521
569
|
|
|
522
570
|
```json
|
|
523
|
-
{
|
|
524
|
-
"main": "master",
|
|
525
|
-
"dev": "develop"
|
|
526
|
-
}
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
### Example: custom prefixes only
|
|
530
|
-
|
|
531
|
-
```json
|
|
532
|
-
{
|
|
533
|
-
"prefixes": {
|
|
534
|
-
"feature": "feat/",
|
|
535
|
-
"bugfix": "fix/"
|
|
536
|
-
}
|
|
537
|
-
}
|
|
571
|
+
{ "main": "master", "dev": "develop" }
|
|
538
572
|
```
|
|
539
573
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
```json
|
|
543
|
-
{
|
|
544
|
-
"name": "my-app",
|
|
545
|
-
"version": "1.0.0",
|
|
546
|
-
"gflows": {
|
|
547
|
-
"main": "main",
|
|
548
|
-
"dev": "development",
|
|
549
|
-
"remote": "upstream"
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
```
|
|
574
|
+
Or in `package.json`: `"gflows": { "main": "main", "dev": "development", "remote": "upstream" }`
|
|
553
575
|
|
|
554
576
|
---
|
|
555
577
|
|
|
556
578
|
## Scripting and CI
|
|
557
579
|
|
|
558
|
-
|
|
559
|
-
- **Skip confirmations:** Use `**-y`/`--yes`** to accept defaults (e.g. "Delete branch after finish?" → no delete unless you also passed `-D`).
|
|
560
|
-
- **Exit codes:** Use them in scripts: `0` success, `1` usage/validation, `2` Git/system error.
|
|
561
|
-
|
|
562
|
-
**Examples:**
|
|
563
|
-
|
|
564
|
-
```bash
|
|
565
|
-
# Require explicit branch when not TTY
|
|
566
|
-
gflows finish feature -B feature/add-login --push -y
|
|
567
|
-
|
|
568
|
-
# List branches for parsing (one per line)
|
|
569
|
-
gflows list feature | while read -r b; do echo "Branch: $b"; done
|
|
570
|
-
|
|
571
|
-
# CI: fail fast on error
|
|
572
|
-
set -e
|
|
573
|
-
gflows start feature ci-job --force
|
|
574
|
-
# ... run tests ...
|
|
575
|
-
gflows finish feature -B feature/ci-job -y
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
**Path:** Use `-C`/`--path` so all git and config resolution use that directory:
|
|
580
|
+
Non-TTY: no pickers; pass branch names explicitly. Use `-y` to skip confirmations. Exit codes: 0 success, 1 validation, 2 Git/state. Use `-C <dir>` to run in another directory.
|
|
579
581
|
|
|
580
582
|
```bash
|
|
581
|
-
gflows -
|
|
582
|
-
gflows -
|
|
583
|
+
bun gflows finish feature -B feature/add-login --push -y
|
|
584
|
+
bun gflows list feature | while read -r b; do echo "$b"; done
|
|
585
|
+
bun gflows -C ./packages/api list
|
|
583
586
|
```
|
|
584
587
|
|
|
585
588
|
---
|
|
586
589
|
|
|
587
590
|
## Exit codes
|
|
588
591
|
|
|
589
|
-
|
|
590
592
|
| Code | Meaning | Typical causes |
|
|
591
593
|
| ----- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
592
594
|
| **0** | Success | Command completed without error. |
|
|
593
|
-
| **1** | Usage / validation | Missing type or name for `start`; invalid branch name or version
|
|
594
|
-
| **2** | Git / system | Not a
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
**Validation (exit 1):** Invalid version (e.g. `start release foo`), invalid branch name (e.g. `feature/bad..name`), or missing required args in non-interactive mode.
|
|
598
|
-
|
|
599
|
-
**Git/state (exit 2):** Repository issues, branch missing, merge conflicts (user must resolve manually), or guards (e.g. cannot finish main/dev, cannot delete main/dev).
|
|
595
|
+
| **1** | Usage / validation | Missing type or name for `start`; invalid branch name or version; wrong/missing positionals when not TTY. |
|
|
596
|
+
| **2** | Git / system | Not a repo; branch not found; dirty tree; merge conflict; rebase/merge in progress; detached HEAD; finish on main/dev; tag exists; push failed. |
|
|
600
597
|
|
|
601
598
|
---
|
|
602
599
|
|
|
603
600
|
## Troubleshooting
|
|
604
601
|
|
|
605
|
-
|
|
606
602
|
| Situation | What to do |
|
|
607
603
|
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
608
604
|
| **"Not a Git repository"** | Run from a directory that contains `.git`, or use `-C <path>` to point to the repo root. |
|
|
@@ -616,54 +612,45 @@ gflows -C ./packages/api list
|
|
|
616
612
|
| **Wrong remote or branch names** | Use `.gflows.json` or `package.json` "gflows" key, or `gflows init --main … --dev … --remote …`. Use `-R` for one-off remote override. |
|
|
617
613
|
|
|
618
614
|
|
|
619
|
-
Use
|
|
615
|
+
Use `-v` for verbose git commands and diagnostics.
|
|
620
616
|
|
|
621
617
|
---
|
|
622
618
|
|
|
623
619
|
## Shell completion
|
|
624
620
|
|
|
625
|
-
Generate and install completion so you can tab-complete commands, types, and (where applicable) branch names.
|
|
626
|
-
|
|
627
621
|
**Bash:**
|
|
628
622
|
|
|
629
623
|
```bash
|
|
630
|
-
source <(gflows completion bash)
|
|
631
|
-
|
|
632
|
-
echo 'source <(gflows completion bash)' >> ~/.bashrc
|
|
624
|
+
source <(bun gflows completion bash)
|
|
625
|
+
echo 'source <(bun gflows completion bash)' >> ~/.bashrc
|
|
633
626
|
```
|
|
634
627
|
|
|
635
628
|
**Zsh:**
|
|
636
629
|
|
|
637
630
|
```bash
|
|
638
|
-
source <(gflows completion zsh)
|
|
639
|
-
|
|
640
|
-
echo 'source <(gflows completion zsh)' >> ~/.zshrc
|
|
631
|
+
source <(bun gflows completion zsh)
|
|
632
|
+
echo 'source <(bun gflows completion zsh)' >> ~/.zshrc
|
|
641
633
|
```
|
|
642
634
|
|
|
643
635
|
**Fish:**
|
|
644
636
|
|
|
645
637
|
```bash
|
|
646
|
-
gflows completion fish | source
|
|
647
|
-
|
|
648
|
-
gflows completion fish > ~/.config/fish/completions/gflows.fish
|
|
638
|
+
bun gflows completion fish | source
|
|
639
|
+
bun gflows completion fish > ~/.config/fish/completions/gflows.fish
|
|
649
640
|
```
|
|
650
641
|
|
|
651
|
-
Completion covers: **commands** (init, start, finish, switch, delete, list, bump, completion, status, help, version), **types** (feature, bugfix, chore, release, hotfix, spike), and **branch names** from local workflow branches when the context expects a branch (e.g. after `switch` or `finish -B`).
|
|
652
|
-
|
|
653
642
|
---
|
|
654
643
|
|
|
655
644
|
## Publishing (maintainers)
|
|
656
645
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
### Commands
|
|
646
|
+
Internal script `scripts/publish.ts`: syncs version from package.json to jsr.json, then publishes to npm and/or JSR. Not in published package.
|
|
660
647
|
|
|
661
648
|
```bash
|
|
662
|
-
bun run publish:all
|
|
663
|
-
bun run publish:all -- --dry-run
|
|
664
|
-
bun run publish:npm
|
|
665
|
-
bun run publish:jsr
|
|
666
|
-
bun run publish:all -- --force
|
|
649
|
+
bun run publish:all
|
|
650
|
+
bun run publish:all -- --dry-run
|
|
651
|
+
bun run publish:npm
|
|
652
|
+
bun run publish:jsr
|
|
653
|
+
bun run publish:all -- --force
|
|
667
654
|
```
|
|
668
655
|
|
|
669
656
|
### Typical release workflow
|