fix(git): disable tag following during pushes
Programmatic `git push` operations should not follow annotated tags configured by a user's `push.followTags = true`. This setting can lead to push failures if the remote rejects tag creation (e.g., in PR-head forks), even if the branch update itself is valid. Adding `--no-follow-tags` explicitly overrides this user setting, ensuring only the specified refspec is pushed and preventing rejections.
This commit is contained in:
@@ -1126,9 +1126,14 @@ export async function commit(cwd: string, message: string, options: CommitOption
|
||||
return runChecked(cwd, args, { signal: options.signal, stdin: message });
|
||||
}
|
||||
|
||||
/** Push the current branch. */
|
||||
/** Push the current branch (branch-scoped: never follows tags). */
|
||||
export async function push(cwd: string, options: PushOptions = {}): Promise<void> {
|
||||
const args = ["push"];
|
||||
// `--no-follow-tags` overrides a user's `push.followTags = true`, which
|
||||
// would otherwise ride every reachable annotated tag along with the
|
||||
// branch — rejected refs ("permission denied") on remotes the user
|
||||
// cannot tag (e.g. PR-head forks), failing the call after the branch
|
||||
// itself already updated. Tool pushes push exactly the named refspec.
|
||||
const args = ["push", "--no-follow-tags"];
|
||||
if (options.forceWithLease) args.push("--force-with-lease");
|
||||
if (options.remote) args.push(options.remote);
|
||||
if (options.refspec) args.push(options.refspec);
|
||||
|
||||
@@ -87,4 +87,27 @@ describe("git subprocess config", () => {
|
||||
"tracked.txt",
|
||||
]);
|
||||
});
|
||||
|
||||
it("scopes pushes to the named refspec, never following tags", async () => {
|
||||
const spawnCalls: SpawnCall[] = [];
|
||||
vi.spyOn(Bun, "spawn").mockImplementation(createSpawnMock(spawnCalls));
|
||||
|
||||
await git.push("/work/pi", { remote: "fork", refspec: "HEAD:refs/heads/feature" });
|
||||
|
||||
// `--no-follow-tags` must override a user's `push.followTags = true`:
|
||||
// implicit tag pushes are rejected on remotes the user cannot tag
|
||||
// (e.g. PR-head forks) and fail the call after the branch updated.
|
||||
expect(spawnCalls).toHaveLength(1);
|
||||
expect(spawnCalls[0]?.cmd).toEqual([
|
||||
"git",
|
||||
"-c",
|
||||
"core.fsmonitor=false",
|
||||
"-c",
|
||||
"core.untrackedCache=false",
|
||||
"push",
|
||||
"--no-follow-tags",
|
||||
"fork",
|
||||
"HEAD:refs/heads/feature",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user