Handle rebase-in-progress detection via state directories and catch rebase errors

REBASE_HEAD can linger after an interrupted rebase, causing false positives.
Checking rebase-merge/ and rebase-apply/ directories matches how git itself
determines rebase state. Also surface rebase failures in the CLI spinner
instead of letting them propagate as unhandled exceptions.
This commit is contained in:
Chris Wanstrath 2026-03-20 22:02:52 -07:00
parent 6175d753f0
commit 2b25170c0c
2 changed files with 11 additions and 4 deletions

View File

@ -21,7 +21,13 @@ export async function action(branch: string) {
await $`git -C ${root} fetch origin ${main}`.nothrow().quiet()
fetchSpin.text = `Rebasing onto origin/${main}`
let conflicts = await git.rebase(`origin/${main}`, worktree)
let conflicts: string[]
try {
conflicts = await git.rebase(`origin/${main}`, worktree)
} catch (err) {
fetchSpin.fail(String((err as Error).message ?? err))
process.exit(1)
}
if (conflicts.length === 0) {
fetchSpin.succeed(`Rebased ${branch} onto ${main}`)
return

View File

@ -153,9 +153,10 @@ export async function abortMerge(cwd: string): Promise<void> {
/** Rebase the current branch onto another. Returns conflicted file paths, or empty array if clean. */
export async function rebase(onto: string, cwd: string): Promise<string[]> {
// Bail early if a rebase is already in progress
const inProgress = await $`git -C ${cwd} rev-parse --verify --quiet REBASE_HEAD`.nothrow().quiet()
if (inProgress.exitCode === 0) {
// Bail early if a rebase is already in progress (check for rebase state directories, not REBASE_HEAD which can be stale)
const rebaseMerge = (await $`git -C ${cwd} rev-parse --git-path rebase-merge`.nothrow().quiet().text()).trim()
const rebaseApply = (await $`git -C ${cwd} rev-parse --git-path rebase-apply`.nothrow().quiet().text()).trim()
if (existsSync(rebaseMerge) || existsSync(rebaseApply)) {
throw new Error(`A rebase is already in progress. Run "git -C ${cwd} rebase --abort" to cancel it first.`)
}