From 29825f2f8a7cc2bb47fd32160046d47b5cf44830 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Sat, 28 Feb 2026 21:08:25 -0800 Subject: [PATCH] Filter detached HEAD pseudo-refs from branch listings - ignore branch lines starting with `(` when parsing `git branch` output - add integration test to verify detached HEAD does not appear as a branch --- apps/server/src/git/Layers/GitCore.test.ts | 12 ++++++++++++ apps/server/src/git/Layers/GitCore.ts | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/server/src/git/Layers/GitCore.test.ts b/apps/server/src/git/Layers/GitCore.test.ts index 2325f8e5f5d5bf7c2013e4f49606fe49601c32ae..2667c7aaa1732d41ee5e8127c33322d0573eb1da 100644 --- a/apps/server/src/git/Layers/GitCore.test.ts +++ b/apps/server/src/git/Layers/GitCore.test.ts @@ -266,6 +266,18 @@ it.layer(TestLayer)("git integration", (it) => { }), ); + it.effect("does not include detached HEAD pseudo-refs as branches", () => + Effect.gen(function* () { + const tmp = yield* makeTmpDir(); + yield* initRepoWithCommit(tmp); + yield* git(tmp, ["checkout", "--detach", "HEAD"]); + + const result = yield* listGitBranches({ cwd: tmp }); + expect(result.branches.some((branch) => branch.name.startsWith("("))).toBe(false); + expect(result.branches.some((branch) => branch.current)).toBe(false); + }), + ); + it.effect("keeps current branch first and sorts the remaining branches by recency", () => Effect.gen(function* () { const tmp = yield* makeTmpDir(); diff --git a/apps/server/src/git/Layers/GitCore.ts b/apps/server/src/git/Layers/GitCore.ts index 76968fcded808bc1cec98bea1fc052c409cd74f9..d3b7fc567bec80dbf64d8668cb2cff195f5532fe 100644 --- a/apps/server/src/git/Layers/GitCore.ts +++ b/apps/server/src/git/Layers/GitCore.ts @@ -82,7 +82,8 @@ function parseBranchLine(line: string): { name: string; current: boolean } | nul const name = trimmed.replace(/^[*+]\s+/, ""); // Exclude symbolic refs like: "origin/HEAD -> origin/main". - if (name.includes(" -> ")) return null; + // Exclude detached HEAD pseudo-refs like: "(HEAD detached at origin/main)". + if (name.includes(" -> ") || name.startsWith("(")) return null; return { name, -- 2.54.0