feat: add support for base branch

This commit is contained in:
Catriel Müller
2026-02-04 13:18:32 -03:00
parent b715b4fbb9
commit 85ffa660f1
3 changed files with 76 additions and 14 deletions
+57 -10
View File
@@ -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 <version> Target upstream version (e.g., v1.1.49)
--commit <hash> 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 <name> Author name for branch prefix
--version <version> Target upstream version (e.g., v1.1.49)
--commit <hash> Target upstream commit hash
--base-branch <name> 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 <name> Author name for branch prefix
```
### analyze.ts
```
Options:
--version <version> Target upstream version
--commit <hash> Target commit hash
--output <file> Output file for report
--version <version> Target upstream version
--commit <hash> Target commit hash
--base-branch <name> Base branch to analyze from (default: dev)
--output <file> 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
+11 -3
View File
@@ -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<string, report.ConflictFile[]>()
@@ -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,
+8 -1
View File
@@ -10,6 +10,7 @@
* Options:
* --version <version> Target upstream version (e.g., v1.1.49)
* --commit <hash> Target upstream commit hash
* --base-branch <name> 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<string> {
async function main() {
const options = parseArgs()
const config = loadConfig()
const config = loadConfig(options.baseBranch ? { baseBranch: options.baseBranch } : undefined)
if (options.verbose) {
logger.setVerbose(true)