gh-stack 0.14.1 → 0.15.0
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 +8 -1
- package/package.json +1 -1
- package/src/commands/submit.ts +37 -1
package/README.md
CHANGED
|
@@ -83,12 +83,19 @@ create <branch-name> [--description <desc>]
|
|
|
83
83
|
Create a new git branch off the current branch and add it to
|
|
84
84
|
the stack. The current branch must already be tracked.
|
|
85
85
|
|
|
86
|
-
submit [-d|--draft] [-n|--no-edit] [-t|--title <t>] [-b|--body <b>] [--body-file <f>] [--dry-run]
|
|
86
|
+
submit [-d|--draft] [-n|--no-edit] [-t|--title <t>] [-b|--body <b>] [--body-file <f>] [--restack] [--dry-run]
|
|
87
87
|
Push all downstack branches to GitHub, create PRs for branches
|
|
88
88
|
that don't have them, number each PR title with its stack position
|
|
89
89
|
`(N/M)`, and update all PR descriptions with stack visualization.
|
|
90
90
|
Idempotent — safe to run repeatedly.
|
|
91
91
|
|
|
92
|
+
--restack: after submitting, restack the branches above the current
|
|
93
|
+
one onto it. submit covers DOWNSTACK (trunk → current); restack covers
|
|
94
|
+
UPSTACK (the children), so together they sync the whole stack from
|
|
95
|
+
wherever you're standing. The everyday loop: drop downstack, fix an
|
|
96
|
+
issue, commit, then `submit --restack` to push the fix and propagate
|
|
97
|
+
it up in one command. Skips cleanly when nothing sits above you.
|
|
98
|
+
|
|
92
99
|
Self-healing: if the current branch isn't tracked in a stack yet,
|
|
93
100
|
submit auto-detects the chain from trunk → current, registers (or
|
|
94
101
|
reconciles into) a stack, then pushes + creates PRs for the whole
|
package/package.json
CHANGED
package/src/commands/submit.ts
CHANGED
|
@@ -4,13 +4,14 @@ import pc from "picocolors";
|
|
|
4
4
|
import { $ } from "bun";
|
|
5
5
|
import * as git from "../lib/git.ts";
|
|
6
6
|
import {
|
|
7
|
+
buildRebaseChain,
|
|
7
8
|
findStackForBranch,
|
|
8
9
|
getOrderedBranches,
|
|
9
10
|
readMetadata,
|
|
10
11
|
writeMetadata,
|
|
11
12
|
} from "../lib/metadata.ts";
|
|
12
13
|
import { isAutoYes } from "../lib/ui.ts";
|
|
13
|
-
import type { StackMetadata } from "../types.ts";
|
|
14
|
+
import type { Stack, StackMetadata } from "../types.ts";
|
|
14
15
|
import { getPrNumber } from "../lib/github.ts";
|
|
15
16
|
import { resolveOrCreateStack } from "../lib/chain.ts";
|
|
16
17
|
import { reconcilePrTitles, refreshStackViz, branchToTitle } from "./update-prs.ts";
|
|
@@ -36,6 +37,8 @@ OPTIONS
|
|
|
36
37
|
-t, --title <title> Set the PR title (current branch) — creates or updates
|
|
37
38
|
-b, --body <body> Set the PR body (current branch) — creates or updates
|
|
38
39
|
--body-file <f> Read PR body from a file
|
|
40
|
+
--restack After submitting, restack the branches above the current
|
|
41
|
+
one onto it (propagate a downstack fix up to children)
|
|
39
42
|
--dry-run Show what would happen without doing anything
|
|
40
43
|
|
|
41
44
|
Updating an existing PR: -t / -b also update the PR for the branch you're on
|
|
@@ -43,10 +46,17 @@ if it already exists — the title keeps its (N/M) stack position, and the body
|
|
|
43
46
|
is replaced with the "Stacked on" block re-merged in. Use this instead of
|
|
44
47
|
gh pr edit so the stack visualization is never clobbered.
|
|
45
48
|
|
|
49
|
+
Restack after submit (--restack): submit covers DOWNSTACK (trunk → current);
|
|
50
|
+
restack covers UPSTACK (the children above current). Together they sync the
|
|
51
|
+
whole stack from wherever you're standing. The common loop: drop downstack,
|
|
52
|
+
fix an issue, commit, then \`submit --restack\` to push the fix and propagate
|
|
53
|
+
it up — one command instead of two. Skips cleanly if nothing sits above you.
|
|
54
|
+
|
|
46
55
|
EXAMPLES
|
|
47
56
|
gh-stack submit # Push + create PRs interactively
|
|
48
57
|
gh-stack submit -n # Push + create PRs with auto-titles
|
|
49
58
|
gh-stack submit -t "My PR" -b "Description" # Explicit title and body
|
|
59
|
+
gh-stack submit --restack # Submit, then restack children onto it
|
|
50
60
|
gh-stack submit --draft # Create new PRs as drafts
|
|
51
61
|
gh-stack submit --dry-run # Preview what would happen
|
|
52
62
|
`;
|
|
@@ -90,6 +100,7 @@ export default async function submit(args: string[]): Promise<void> {
|
|
|
90
100
|
|
|
91
101
|
const draftFlag = args.includes("--draft") || args.includes("-d");
|
|
92
102
|
const dryRun = args.includes("--dry-run");
|
|
103
|
+
const restackFlag = args.includes("--restack");
|
|
93
104
|
|
|
94
105
|
// Parse value flags
|
|
95
106
|
let titleFlag: string | undefined;
|
|
@@ -355,6 +366,7 @@ export default async function submit(args: string[]): Promise<void> {
|
|
|
355
366
|
`Dry run complete: would push ${scope.length}, create ${created}, update ${existing} PR(s)`,
|
|
356
367
|
),
|
|
357
368
|
);
|
|
369
|
+
if (restackFlag) await maybeRestack(stack, branch, true);
|
|
358
370
|
return;
|
|
359
371
|
}
|
|
360
372
|
|
|
@@ -388,4 +400,28 @@ export default async function submit(args: string[]): Promise<void> {
|
|
|
388
400
|
(viz.unchanged > 0 ? `, ${viz.unchanged} unchanged` : ""),
|
|
389
401
|
),
|
|
390
402
|
);
|
|
403
|
+
|
|
404
|
+
// ── --restack: propagate a downstack fix up to the children ──
|
|
405
|
+
// submit owns DOWNSTACK (trunk → current); restack owns UPSTACK (the branches
|
|
406
|
+
// above current). Running both from one branch syncs the whole stack.
|
|
407
|
+
if (restackFlag) await maybeRestack(stack, branch, false);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Chain into `restack` from the current branch after a submit, so a downstack
|
|
412
|
+
* fix propagates up to its children in one command. No-op (with a friendly
|
|
413
|
+
* note) when nothing sits above the current branch — there's nothing to rebase.
|
|
414
|
+
*/
|
|
415
|
+
async function maybeRestack(stack: Stack, branch: string, dryRun: boolean): Promise<void> {
|
|
416
|
+
// buildRebaseChain returns the current branch + all its descendants; a length
|
|
417
|
+
// of 1 means it's the top of its line, so there's nothing above to restack.
|
|
418
|
+
if (buildRebaseChain(stack, branch).length <= 1) {
|
|
419
|
+
console.log();
|
|
420
|
+
p.log.info(pc.dim(`--restack: nothing sits above ${pc.yellow(branch)} — nothing to restack.`));
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
console.log();
|
|
425
|
+
const { default: restack } = await import("./restack.ts");
|
|
426
|
+
await restack(dryRun ? ["--dry-run"] : []);
|
|
391
427
|
}
|