Subject: Re: Commands using -h as an option don't work consistently

From: Junio C Hamano <[email-masked]>
Date: Wed, 29 May 2024 15:22:09 -0700

Kevin Day <[email-masked]> writes:

> Because of a bug in parse-options.c, any command that has a '-h' option will sometimes display the usage page instead of executing. For example, ls-remote has two options:
>
>     -t, --[no-]tags       limit to tags
>     -h, --[no-]heads      limit to heads
>
> git ls-remote --heads  #works
> git ls-remote --tags  #works
> git ls-remote -t  #works
> git ls-remote -t -h  #works
> git ls-remote -h  #shows the help page
>
> This is because of these lines in parse-options.c:
>
> /* lone -h asks for help */
> if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h"))
> goto show_usage;
>
> This is being executed before it looks to see if there actually is a -h option.

This is very much deliberate design.  I think in these cases we make
an unambiguous longhand (e.g. "--heads" we see above) available, or
you can explicitly say the remote, i.e. "git ls-remote -h origin",
and that has been the officially accepted "solution".

Let's see what improvements you bring to the table.

> The options I see:
>
> 1) Fix -h handling and add ignores and fixes where possible to the
> failing tests and try to not use -h as an option for anything new.

I do not quite understand the former half, but "try not to use -h
for new things" is a very good idea and it is pretty much what we
have been doing.

    Note: There however is a scenario where we cannot avoid it---if
    we were trying to match/mimick some established external
    command, we may have to use the same "-h" as they use (e.g.,
    "git grep -h -e ..." tries to mimick "grep -h -e ...").  Even in
    that case, because "git grep -h" alone would not make any sense
    without any pattern, the command behaves very sensibly, by the
    way.

> 2) Change -h to -H or something, but this breaks backwards compatibility

As you said it yourself, this is a non starter.

> 3) Fix it so that -h works if a command uses it, and additionally
> make a new global option -? or --usage or something that always
> shows the usage page and change tests to use that, while leaving
> -h sometimes showing usage and sometimes executing the option to
> preserve as much backward compatibility as possible.

Reading this and then going back to the ls-remote examples you gave
earlier, I do not think the current behaviour is all that bad,
relative to what is being proposed, except for an explicit support
for "-?".

We can certainly add support for "-?", but the behaviour when "-?"
is not used (and when "-h" is used) would not have to change from
the current behaviour, and that would still be serviceable, I
presume?

We actually do not have to *add* support for "-?", as it comes with
parse-options for free ;-)

    $ git ls-remote -\?
    error: unknown switch '?'
    usage: git ls-remote ...
	... the same "ls-remote -h" output given here ...

So, I dunno.