From 3fc1fdd75fec05e5014f126874dc06d1aa7077b1 Mon Sep 17 00:00:00 2001 From: EDM115 Date: Sun, 29 Mar 2026 14:51:31 +0200 Subject: [PATCH 1/3] fix(server): parse git branches correctly when column.ui is enabled --- apps/server/src/git/Layers/GitCore.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/server/src/git/Layers/GitCore.ts b/apps/server/src/git/Layers/GitCore.ts index 64ed409508..c84a01b3cb 100644 --- a/apps/server/src/git/Layers/GitCore.ts +++ b/apps/server/src/git/Layers/GitCore.ts @@ -1423,7 +1423,7 @@ export const makeGitCore = Effect.fn("makeGitCore")(function* (options?: { const localBranchResult = yield* executeGit( "GitCore.listBranches.branchNoColor", input.cwd, - ["branch", "--no-color"], + ["branch", "--no-color", "--no-column"], { timeoutMs: 10_000, allowNonZeroExit: true, @@ -1438,7 +1438,7 @@ export const makeGitCore = Effect.fn("makeGitCore")(function* (options?: { return yield* createGitCommandError( "GitCore.listBranches", input.cwd, - ["branch", "--no-color"], + ["branch", "--no-color", "--no-column"], stderr || "git branch failed", ); } @@ -1446,7 +1446,7 @@ export const makeGitCore = Effect.fn("makeGitCore")(function* (options?: { const remoteBranchResultEffect = executeGit( "GitCore.listBranches.remoteBranches", input.cwd, - ["branch", "--no-color", "--remotes"], + ["branch", "--no-color", "--no-column", "--remotes"], { timeoutMs: 10_000, allowNonZeroExit: true, @@ -1814,6 +1814,7 @@ export const makeGitCore = Effect.fn("makeGitCore")(function* (options?: { runGitStdout("GitCore.listLocalBranchNames", cwd, [ "branch", "--list", + "--no-column", "--format=%(refname:short)", ]).pipe( Effect.map((stdout) => From 90401c555d97f4ce21ab86148cfce9245e827075 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Tue, 31 Mar 2026 17:46:18 -0700 Subject: [PATCH 2/3] Handle column-formatted git branch output - Add coverage for `git branch` parsing when `column.ui=always` - Prevent merged branch names when Git formats output into columns --- apps/server/src/git/Layers/GitCore.test.ts | 58 ++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/apps/server/src/git/Layers/GitCore.test.ts b/apps/server/src/git/Layers/GitCore.test.ts index 547a69e7e1..dfcf21d3ee 100644 --- a/apps/server/src/git/Layers/GitCore.test.ts +++ b/apps/server/src/git/Layers/GitCore.test.ts @@ -313,6 +313,64 @@ it.layer(TestLayer)("git integration", (it) => { }), ); + it.effect("parses separate branch names when column.ui is always enabled", () => + Effect.gen(function* () { + const tmp = yield* makeTmpDir(); + const { initialBranch } = yield* initRepoWithCommit(tmp); + const createdBranchNames = [ + "go-bin", + "copilot/rewrite-cli-in-go", + "copilot/rewrite-cli-in-rust", + ] as const; + for (const branchName of createdBranchNames) { + yield* (yield* GitCore).createBranch({ cwd: tmp, branch: branchName }); + } + yield* git(tmp, ["config", "column.ui", "always"]); + + const rawBranchOutput = yield* git(tmp, ["branch", "--no-color"], { + ...process.env, + COLUMNS: "120", + }); + expect( + rawBranchOutput + .split("\n") + .some( + (line) => + createdBranchNames.filter((branchName) => line.includes(branchName)).length >= 2, + ), + ).toBe(true); + + const realGitCore = yield* GitCore; + const core = yield* makeIsolatedGitCore((input) => + realGitCore.execute( + input.args[0] === "branch" + ? { + ...input, + env: { ...input.env, COLUMNS: "120" }, + } + : input, + ), + ); + + const result = yield* core.listBranches({ cwd: tmp }); + const localBranchNames = result.branches + .filter((branch) => !branch.isRemote) + .map((branch) => branch.name); + + expect(localBranchNames).toHaveLength(4); + expect(localBranchNames).toEqual( + expect.arrayContaining([initialBranch, ...createdBranchNames]), + ); + expect( + localBranchNames.some( + (branchName) => + createdBranchNames.filter((createdBranch) => branchName.includes(createdBranch)) + .length >= 2, + ), + ).toBe(false); + }), + ); + it.effect("isDefault is false when no remote exists", () => Effect.gen(function* () { const tmp = yield* makeTmpDir(); From 8fdae985382d3fdcf5eac829fc76b460dd445df0 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Tue, 31 Mar 2026 17:58:57 -0700 Subject: [PATCH 3/3] Expect `git branch` to disable columns for remotes - Update the GitCore integration test to match the `branch --no-column` invocation - Covers the remote-branches failure path with the corrected command shape --- apps/server/src/git/Layers/GitCore.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/git/Layers/GitCore.test.ts b/apps/server/src/git/Layers/GitCore.test.ts index dfcf21d3ee..561b98aa78 100644 --- a/apps/server/src/git/Layers/GitCore.test.ts +++ b/apps/server/src/git/Layers/GitCore.test.ts @@ -1882,7 +1882,7 @@ it.layer(TestLayer)("git integration", (it) => { let didFailRemoteBranches = false; let didFailRemoteNames = false; const core = yield* makeIsolatedGitCore((input) => { - if (input.args.join(" ") === "branch --no-color --remotes") { + if (input.args.join(" ") === "branch --no-color --no-column --remotes") { didFailRemoteBranches = true; return Effect.fail( new GitCommandError({