fix: Use update-ref for fast-forward to avoid dirty working tree failures

fastForwardBranch used git merge --ff-only which fails when the clone
has uncommitted files. This caused the ff to be silently skipped, the
merge to proceed on stale main, and the push to fail (non-fast-forward).

Switched to update-ref which only moves the branch pointer without
touching the working tree.
This commit is contained in:
Lukas May
2026-03-06 12:34:21 +01:00
parent 6a76e17cef
commit 5d1292c7ad

View File

@@ -208,7 +208,18 @@ export class SimpleGitBranchManager implements BranchManager {
async fastForwardBranch(repoPath: string, branch: string, remote = 'origin'): Promise<void> { async fastForwardBranch(repoPath: string, branch: string, remote = 'origin'): Promise<void> {
const git = simpleGit(repoPath); const git = simpleGit(repoPath);
const remoteBranch = `${remote}/${branch}`; const remoteBranch = `${remote}/${branch}`;
await git.raw(['merge', '--ff-only', remoteBranch, branch]);
// Verify it's a genuine fast-forward (branch is ancestor of remote)
try {
await git.raw(['merge-base', '--is-ancestor', branch, remoteBranch]);
} catch {
throw new Error(`Cannot fast-forward ${branch}: it has diverged from ${remoteBranch}`);
}
// Use update-ref instead of git merge so dirty working trees don't block it.
// The clone may have uncommitted agent work; we only need to advance the ref.
const targetCommit = (await git.raw(['rev-parse', remoteBranch])).trim();
await git.raw(['update-ref', `refs/heads/${branch}`, targetCommit]);
log.info({ repoPath, branch, remoteBranch }, 'fast-forwarded branch'); log.info({ repoPath, branch, remoteBranch }, 'fast-forwarded branch');
} }