Skip to content

Commit b787703

Browse files
only21milclaude
andcommitted
fix(server): selected-file commits stop when the index reset fails
Committing selected files resets the index first, but a failed `git reset` was swallowed. If another git process held `.git/index.lock` during the reset, the selected files were added to the old index and the commit also included files the user had staged but left out of the selection. Let the reset failure propagate so the commit stops with a GitCommandError and nothing is committed. `git reset` on an unborn branch exits 0, so no case needs the swallow anymore. Co-Authored-By: Claude Opus 5.5 <[email protected]>
1 parent 15fe283 commit b787703

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

‎apps/server/src/vcs/GitVcsDriverCore.test.ts‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4824,6 +4824,31 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => {
48244824
}),
48254825
);
48264826

4827+
it.effect("stops a selected-file commit when another process holds the index lock", () =>
4828+
Effect.gen(function* () {
4829+
const cwd = yield* makeTmpDir();
4830+
yield* initRepoWithCommit(cwd);
4831+
const head = yield* git(cwd, ["rev-parse", "HEAD"]);
4832+
yield* writeTextFile(cwd, "a.txt", "a\n");
4833+
yield* writeTextFile(cwd, "staged.txt", "staged\n");
4834+
yield* git(cwd, ["add", "staged.txt"]);
4835+
const lockPath = (yield* Path.Path).join(cwd, ".git", "index.lock");
4836+
yield* (yield* FileSystem.FileSystem).writeFileString(lockPath, "");
4837+
const { driver } = yield* makeDriverReleasingLock(
4838+
(args) => args.includes("reset"),
4839+
lockPath,
4840+
);
4841+
4842+
const error = yield* driver
4843+
.commit(cwd, "Add a", "", { stage: { filePaths: ["a.txt"] } })
4844+
.pipe(Effect.flip);
4845+
4846+
assert.equal(error.operation, "GitVcsDriver.commit.reset");
4847+
assert.equal(yield* git(cwd, ["rev-parse", "HEAD"]), head);
4848+
assert.equal(yield* git(cwd, ["diff", "--cached", "--name-only"]), "staged.txt");
4849+
}),
4850+
);
4851+
48274852
it.effect.each([
48284853
{ location: "root", ref: "refs/heads/MERGE_HEAD" },
48294854
{ location: "nested", ref: "refs/heads/MERGE_HEAD" },

‎apps/server/src/vcs/GitVcsDriverCore.ts‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2421,9 +2421,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
24212421
"Cannot commit selected files during a merge. Commit all files to finish the merge.",
24222422
});
24232423
}
2424-
yield* runGit("GitVcsDriver.commit.reset", cwd, ["reset"]).pipe(
2425-
Effect.catchTags({ GitCommandError: () => Effect.void }),
2426-
);
2424+
yield* runGit("GitVcsDriver.commit.reset", cwd, ["reset"]);
24272425
}
24282426
yield* runGit(
24292427
"GitVcsDriver.commit.addSelected",

0 commit comments

Comments
 (0)