diff --git a/script/upstream/README.md b/script/upstream/README.md index 5a25a2d4cd..9440171e53 100644 --- a/script/upstream/README.md +++ b/script/upstream/README.md @@ -20,6 +20,9 @@ bun run merge.ts --version v1.1.49 # Dry-run to preview what would happen bun run merge.ts --version v1.1.49 --dry-run + +# Use a different base branch (e.g., for incremental merges) +bun run merge.ts --version v1.1.50 --base-branch catrielmuller/kilo-opencode-v1.1.44 ``` ## Scripts @@ -207,22 +210,66 @@ The only remaining conflicts are files with **actual code differences** - files ``` Options: - --version Target upstream version (e.g., v1.1.49) - --commit Target upstream commit hash - --dry-run Preview changes without applying them - --no-push Don't push branches to remote - --report-only Only generate conflict report - --verbose Enable verbose logging - --author Author name for branch prefix + --version Target upstream version (e.g., v1.1.49) + --commit Target upstream commit hash + --base-branch Base branch to merge into (default: dev) + --dry-run Preview changes without applying them + --no-push Don't push branches to remote + --report-only Only generate conflict report + --verbose Enable verbose logging + --author Author name for branch prefix ``` ### analyze.ts ``` Options: - --version Target upstream version - --commit Target commit hash - --output Output file for report + --version Target upstream version + --commit Target commit hash + --base-branch Base branch to analyze from (default: dev) + --output Output file for report +``` + +## Using Custom Base Branches + +By default, upstream merges start from the `dev` branch. However, you can use `--base-branch` to start from a different branch. This is useful for: + +### Incremental Merges + +When working on multiple upstream versions, you can create a chain of merge PRs: + +```bash +# First merge: v1.1.44 into dev +bun run merge.ts --version v1.1.44 + +# Create PR: catrielmuller/kilo-opencode-v1.1.44 -> dev + +# Second merge: v1.1.50 based on the previous PR (without waiting for approval) +bun run merge.ts --version v1.1.50 --base-branch catrielmuller/kilo-opencode-v1.1.44 + +# Create PR: catrielmuller/kilo-opencode-v1.1.50 -> catrielmuller/kilo-opencode-v1.1.44 +# OR: catrielmuller/kilo-opencode-v1.1.50 -> dev (once first PR is merged) +``` + +### Benefits + +- **Work in parallel**: Don't wait for PR approval to start the next merge +- **Isolation**: Each merge is independent and easier to review +- **Flexibility**: Can adjust the PR chain as needed +- **Cleaner history**: Related merges can be grouped together + +### Example Workflow + +```bash +# 1. Analyze next version from your WIP branch +bun run analyze.ts --version v1.1.50 --base-branch catrielmuller/kilo-opencode-v1.1.44 + +# 2. Run the merge +bun run merge.ts --version v1.1.50 --base-branch catrielmuller/kilo-opencode-v1.1.44 + +# 3. Create PR from catrielmuller/kilo-opencode-v1.1.50 +# - Target: catrielmuller/kilo-opencode-v1.1.44 (if first PR not merged yet) +# - Target: dev (if first PR is already merged) ``` ## Manual Conflict Resolution diff --git a/script/upstream/analyze.ts b/script/upstream/analyze.ts index ac4f3188b4..c2b8c677ae 100644 --- a/script/upstream/analyze.ts +++ b/script/upstream/analyze.ts @@ -7,19 +7,21 @@ * Usage: * bun run script/upstream/analyze.ts --version v1.1.49 * bun run script/upstream/analyze.ts --commit abc123 + * bun run script/upstream/analyze.ts --version v1.1.49 --base-branch catrielmuller/kilo-opencode-v1.1.44 */ import { $ } from "bun" import * as git from "./utils/git" import * as version from "./utils/version" import * as report from "./utils/report" -import { defaultConfig } from "./utils/config" +import { defaultConfig, loadConfig } from "./utils/config" import { header, info, success, warn, error, divider, list } from "./utils/logger" interface AnalyzeOptions { version?: string commit?: string output?: string + baseBranch?: string } function parseArgs(): AnalyzeOptions { @@ -41,11 +43,17 @@ function parseArgs(): AnalyzeOptions { options.output = args[outputIdx + 1] } + const baseBranchIdx = args.indexOf("--base-branch") + if (baseBranchIdx !== -1 && args[baseBranchIdx + 1]) { + options.baseBranch = args[baseBranchIdx + 1] + } + return options } async function main() { const options = parseArgs() + const config = loadConfig(options.baseBranch ? { baseBranch: options.baseBranch } : undefined) header("Upstream Change Analysis") @@ -93,7 +101,7 @@ async function main() { info("Analyzing changes...") // Use commit hash directly since we may not have the tag fetched locally - const conflicts = await report.analyzeConflicts(target.commit, defaultConfig.baseBranch, defaultConfig.keepOurs) + const conflicts = await report.analyzeConflicts(target.commit, config.baseBranch, config.keepOurs) // Group by type const byType = new Map() @@ -149,7 +157,7 @@ async function main() { timestamp: new Date().toISOString(), upstreamVersion: target.version, upstreamCommit: target.commit, - baseBranch: defaultConfig.baseBranch, + baseBranch: config.baseBranch, mergeBranch: "", totalConflicts: conflicts.length, conflicts, diff --git a/script/upstream/merge.ts b/script/upstream/merge.ts index b31cbc571c..fa52945178 100644 --- a/script/upstream/merge.ts +++ b/script/upstream/merge.ts @@ -10,6 +10,7 @@ * Options: * --version Target upstream version (e.g., v1.1.49) * --commit Target upstream commit hash + * --base-branch Base branch to merge into (default: dev) * --dry-run Preview changes without applying them * --no-push Don't push branches to remote * --report-only Only generate conflict report, don't merge @@ -52,6 +53,7 @@ import { resolveLockFileConflicts, regenerateLockFiles } from "./transforms/lock interface MergeOptions { version?: string commit?: string + baseBranch?: string dryRun: boolean push: boolean reportOnly: boolean @@ -84,6 +86,11 @@ function parseArgs(): MergeOptions { options.author = args[authorIdx + 1] } + const baseBranchIdx = args.indexOf("--base-branch") + if (baseBranchIdx !== -1 && args[baseBranchIdx + 1]) { + options.baseBranch = args[baseBranchIdx + 1] + } + return options } @@ -109,7 +116,7 @@ async function createBackupBranch(baseBranch: string): Promise { async function main() { const options = parseArgs() - const config = loadConfig() + const config = loadConfig(options.baseBranch ? { baseBranch: options.baseBranch } : undefined) if (options.verbose) { logger.setVerbose(true)