mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-19 01:51:21 +08:00
chore(upstream): implement compatibility base tracking for merges
Update the upstream merge script to identify and link to the previous compatibility commit. This ensures that pre-merge transformations maintain a proper commit history by using multiple parents when a prior compatibility base is found, rather than creating disconnected commits. - Add `findLatestCompatCommit` to locate previous compatibility commits - Implement `commitTree` and `updateBranch` for low-level git manipulation - Update `merge.ts` to integrate compatibility base detection and multi-parent commits
This commit is contained in:
@@ -429,6 +429,15 @@ async function main() {
|
||||
await git.createBranch(opencodeBranch)
|
||||
logger.info(`Created opencode branch: ${opencodeBranch}`)
|
||||
|
||||
const prior = await git.findLatestCompatCommit(config.baseBranch, targetVersion.commit)
|
||||
if (prior) {
|
||||
logger.info(
|
||||
`Found previous compatibility base: ${prior.message} (${prior.commit.slice(0, 8)}) from upstream ${prior.upstream.slice(0, 8)}`,
|
||||
)
|
||||
} else {
|
||||
logger.warn("No previous compatibility base found; merge base will remain pristine upstream")
|
||||
}
|
||||
|
||||
// Step 6: Apply ALL transformations to opencode branch (pre-merge)
|
||||
// This reduces conflicts by transforming upstream code to Kilo conventions BEFORE merging
|
||||
logger.step(6, 8, "Applying transformations to opencode branch (pre-merge)...")
|
||||
@@ -524,7 +533,15 @@ async function main() {
|
||||
|
||||
// Commit all transformations
|
||||
await git.stageAll()
|
||||
await git.commit(`refactor: kilo compat for ${targetVersion.tag}`)
|
||||
const compatMessage = `refactor: kilo compat for ${targetVersion.tag}`
|
||||
if (prior) {
|
||||
const tree = await git.writeTree()
|
||||
const commit = await git.commitTree(tree, compatMessage, [targetVersion.commit, prior.commit])
|
||||
await git.updateBranch(opencodeBranch, commit)
|
||||
await git.checkout(opencodeBranch)
|
||||
} else {
|
||||
await git.commit(compatMessage)
|
||||
}
|
||||
logger.success("Committed pre-merge transformations")
|
||||
|
||||
// Step 7: Merge into Kilo branch
|
||||
|
||||
@@ -15,6 +15,12 @@ export interface RemoteInfo {
|
||||
url: string
|
||||
}
|
||||
|
||||
export interface CompatBase {
|
||||
commit: string
|
||||
upstream: string
|
||||
message: string
|
||||
}
|
||||
|
||||
export async function getCurrentBranch(): Promise<string> {
|
||||
const result = await $`git rev-parse --abbrev-ref HEAD`.text()
|
||||
return result.trim()
|
||||
@@ -177,6 +183,55 @@ export async function getCommitHash(ref: string): Promise<string> {
|
||||
return result.trim()
|
||||
}
|
||||
|
||||
export async function getCommitParents(ref: string): Promise<string[]> {
|
||||
const result = await $`git show --no-patch --format=%P ${ref}`.text()
|
||||
return result
|
||||
.trim()
|
||||
.split(/\s+/)
|
||||
.filter((parent) => parent.length > 0)
|
||||
}
|
||||
|
||||
export async function writeTree(): Promise<string> {
|
||||
const result = await $`git write-tree`.text()
|
||||
return result.trim()
|
||||
}
|
||||
|
||||
export async function commitTree(tree: string, message: string, parents: string[]): Promise<string> {
|
||||
const args = parents.flatMap((parent) => ["-p", parent])
|
||||
const result = await $`git commit-tree ${tree} ${args} -m ${message}`.text()
|
||||
return result.trim()
|
||||
}
|
||||
|
||||
export async function updateBranch(name: string, commit: string): Promise<void> {
|
||||
await $`git update-ref refs/heads/${name} ${commit}`
|
||||
}
|
||||
|
||||
export async function findLatestCompatCommit(base: string, target: string): Promise<CompatBase | null> {
|
||||
const grep = "^refactor: kilo compat for "
|
||||
const result = await $`git log --format=%H%x00%s --grep=${grep} ${base}`.quiet().nothrow()
|
||||
if (result.exitCode !== 0) {
|
||||
throw new Error(`Failed to search compatibility commits: ${result.stderr.toString()}`)
|
||||
}
|
||||
|
||||
const lines = result.stdout
|
||||
.toString()
|
||||
.trim()
|
||||
.split("\n")
|
||||
.filter((line) => line.length > 0)
|
||||
|
||||
for (const line of lines) {
|
||||
const [commit, message = ""] = line.split("\0")
|
||||
if (!commit) continue
|
||||
|
||||
const parents = await getCommitParents(commit)
|
||||
for (const parent of parents) {
|
||||
if (await isAncestor(parent, target)) return { commit, upstream: parent, message }
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if `commit` is an ancestor of `ref` (i.e. reachable from `ref`).
|
||||
* Uses `git merge-base --is-ancestor`, which exits 0 for yes, 1 for no.
|
||||
|
||||
Reference in New Issue
Block a user