merge #3845: preserve agent commit history across isolated branch merges

This commit is contained in:
can1357
2026-06-30 03:01:02 +02:00
6 changed files with 420 additions and 32 deletions
+36
View File
@@ -74,8 +74,20 @@ export interface StatusOptions {
readonly z?: boolean;
}
export interface CommitAuthor {
readonly date?: string;
readonly email: string;
readonly name: string;
}
export interface CommitDetails {
readonly author: CommitAuthor;
readonly message: string;
}
export interface CommitOptions {
readonly allowEmpty?: boolean;
readonly author?: CommitAuthor;
readonly files?: readonly string[];
readonly signal?: AbortSignal;
}
@@ -1122,6 +1134,10 @@ export const stage = {
/** Create a commit with the given message (passed via stdin). */
export async function commit(cwd: string, message: string, options: CommitOptions = {}): Promise<GitCommandResult> {
const args = ["commit", "-F", "-"];
if (options.author) {
args.push(`--author=${options.author.name} <${options.author.email}>`);
if (options.author.date) args.push(`--date=${options.author.date}`);
}
if (options.allowEmpty) args.push("--allow-empty");
if (options.files?.length) args.push("--", ...options.files);
return runChecked(cwd, args, { signal: options.signal, stdin: message });
@@ -1195,6 +1211,19 @@ export const show = Object.assign(
},
);
/** Read commit message and author metadata for replay/rewrite flows. */
export async function commitDetails(cwd: string, revision: string, signal?: AbortSignal): Promise<CommitDetails> {
const raw = await runText(cwd, ["show", "-s", "--format=%an%x00%ae%x00%aI%x00%B", revision], {
readOnly: true,
signal,
});
const [name = "", email = "", date = "", ...messageParts] = raw.split("\0");
return {
author: { date, email, name },
message: messageParts.join("\0").replace(/\n$/, ""),
};
}
// ════════════════════════════════════════════════════════════════════════════
// API: log
// ════════════════════════════════════════════════════════════════════════════
@@ -1212,6 +1241,13 @@ export const log = {
},
};
export const revList = {
/** Commits in `base..head`, oldest first. */
async range(cwd: string, base: string, head: string, signal?: AbortSignal): Promise<string[]> {
return splitLines(await runText(cwd, ["rev-list", "--reverse", `${base}..${head}`], { readOnly: true, signal }));
},
};
// ════════════════════════════════════════════════════════════════════════════
// API: branch
// ════════════════════════════════════════════════════════════════════════════