Skip to content

CreateTag(name) without Annotating fails with "There was a problem with the editor" when tag.gpgSign=true, so lightweight tags cannot be created #183

Description

@matt-edmondson

What's wrong

CreateTag(name) without Annotating(...) is documented to create a lightweight tag (Builders/GitTagCreateBuilder.cs:14-18). The builder emits git tag --end-of-options <name> [<target>] (GitTagCreateBuilder.cs:98-125) and leaves signing to the host's config.

When tag.gpgSign=true is set, git ignores the request for a lightweight tag. It tries to make a signed annotated tag instead, and a signed tag needs a message, so git opens the configured editor. People who sign their work often set this option in ~/.gitconfig next to commit.gpgSign. The library pins neither GIT_EDITOR nor --no-sign (Execution/RunCommandGitProcessRunner.cs:53-54 overlays only GIT_TERMINAL_PROMPT and LC_ALL). The interface's own remarks say an editor is something "no invocation this library makes could ever answer" (GitTagCreateBuilder.cs:35-36).

Failure scenario

Reproduced with git 2.43:

git init -q t && cd t && git commit -q --allow-empty -m x
git -c tag.gpgSign=true tag --end-of-options v1 </dev/null
# Standard input is not a terminal
# error: There was a problem with the editor 'editor'.
# Please supply the message using either -m or -F option.
# exit 1, no tag created

Through the library, repository.CreateTag("v1".As<GitTagName>()).ExecuteAsync() throws GitCommandException with that editor diagnostic. The caller asked for a lightweight tag and nothing more, and the message says nothing about signing. If the host process's stdin is a terminal, the invocation may also start the user's editor and wait for it, depending on how the runner wires stdin.

git -c tag.gpgSign=true tag --no-sign v1 succeeds, and git cat-file -t v1 reports commit, which means a real lightweight tag.

Suggested fix / acceptance criteria

  • When no message was given (the lightweight path), emit --no-sign before the operands. A lightweight tag cannot be signed, so this pins what the caller asked for. The annotated path stays as it is, so a user's signing preference still applies there.
  • Builder test: the argument vector for CreateTag(name) contains --no-sign, and the one for CreateTag(name).Annotating(msg) does not.
  • Integration test: with tag.gpgSign=true in the test repository's local config, CreateTag(name).ExecuteAsync() succeeds, and Tags() reports the tag at HEAD's commit.
  • --no-sign on git tag is older than the --end-of-options floor the library already depends on (No minimum git version is asserted or documented; on git < 2.24 every operand-taking verb fails with an opaque "unknown option" error #164), so it adds no new minimum version.

Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions