* Unexpected exit code for --help with rev-parse --parseopt
@ 2026-03-15 0:52 brian m. carlson
2026-03-15 3:14 ` Jeff King
2026-03-16 22:07 ` [PATCH] rev-parse: have --parseopt callers exit 0 on --help brian m. carlson
0 siblings, 2 replies; 14+ messages in thread
From: brian m. carlson @ 2026-03-15 0:52 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 2295 bytes --]
I use git rev-parse --parseopt to parse command-line options in various
script. I've noticed that it exits 129 if the options are invalid,
which is fine, but that it also exits 129 if --help or -h are given,
which is not.
The standard philosophy is that if the user explicitly asked for help,
then help output should be printed to standard output (since that's what
the user asked for) and it should exit 0, since the program fulfilled
the user's request successfully. If the help output is provided because
the user provided an invalid option or argument, then the output should
Go to standard error (since it's an error message) and the program
should exit unsuccessfully (since it did not fulfill the user's request
successfully).
Git gets the location of the output just fine, but currently there's no
way for a program to detect the help output and exit successfully. Note
that Git subcommands don't have this problem because Git itself
intercepts the help output and sends it to man (or whatever the user has
configured), which then exits successfully.
I'd like to fix this in git rev-parse --parseopt (that is, I am willing
to send a patch), but I'm unsure about the best way to go about this.
Does anyone have ideas about how they'd like this to be fixed? I could
simply change the exit code in this case or I could add an option to
control this behaviour for backwards compatibility.
Example:
----
#!/bin/sh
OPTS_SPEC="\
foo-cmd [<options>] <args>...
Do stuff.
--
h,help! show this help
o,output= output to this file
d,dir= specify dependencies relative to this directory
"
main () {
eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
# Do something with the options here.
}
main "$@"
----
Output:
----
% ./foo-cmd --help >/dev/null; echo $?
129
% ./foo-cmd -h >/dev/null; echo $?
129
% ./foo-cmd --bassoon >/dev/null; echo $?
error: unknown option `bassoon'
usage: foo-cmd [<options>] <args>...
Do stuff.
-h, --help show this help
-o, --[no-]output ... output to this file
-d, --[no-]dir ... specify dependencies relative to this directory
129
----
--
brian m. carlson (they/them)
Toronto, Ontario, CA
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: Unexpected exit code for --help with rev-parse --parseopt 2026-03-15 0:52 Unexpected exit code for --help with rev-parse --parseopt brian m. carlson @ 2026-03-15 3:14 ` Jeff King 2026-03-15 16:59 ` brian m. carlson 2026-03-16 22:07 ` [PATCH] rev-parse: have --parseopt callers exit 0 on --help brian m. carlson 1 sibling, 1 reply; 14+ messages in thread From: Jeff King @ 2026-03-15 3:14 UTC (permalink / raw) To: brian m. carlson; +Cc: git On Sun, Mar 15, 2026 at 12:52:22AM +0000, brian m. carlson wrote: > I use git rev-parse --parseopt to parse command-line options in various > script. I've noticed that it exits 129 if the options are invalid, > which is fine, but that it also exits 129 if --help or -h are given, > which is not. > > The standard philosophy is that if the user explicitly asked for help, > then help output should be printed to standard output (since that's what > the user asked for) and it should exit 0, since the program fulfilled > the user's request successfully. If the help output is provided because > the user provided an invalid option or argument, then the output should > Go to standard error (since it's an error message) and the program > should exit unsuccessfully (since it did not fulfill the user's request > successfully). I agree with this philosophy in general, but there's catch here with "rev-parse --parseopt", because it's running as a separate program. It needs to signal to the calling program that "-h" was seen, the program should not proceed normally (because rev-parse already dumped help output). So if your proposal is to just exit with code 0 from rev-parse, I don't think that works. My first instinct is that it would have to exit with some other well-known code, the callers would recognize that, and then exit themselves (with code 0). But there's a little more to the story. The output of --parseopt is meant to be eval'd by the shell. And so when it works, we get a "set" command: $ git rev-parse --parseopt <input -- --output=foo set -- -o 'foo' -- And when there's an error, it dumps the usage text straight to stderr and exits 129: $ git rev-parse --parseopt <input -- --foo error: unknown option `foo' usage: foo-cmd [<options>] <args>... Do stuff. -h, --help show this help -o, --[no-]output ... output to this file -d, --[no-]dir ... specify dependencies relative to this directory But when the user asks for "-h", we get a here-doc! Like this: $ git rev-parse --parseopt <input -- -h cat <<\EOF usage: foo-cmd [<options>] <args>... Do stuff. -h, --help show this help -o, --[no-]output ... output to this file -d, --[no-]dir ... specify dependencies relative to this directory EOF So the calling program runs that cat command. And I think what you really want is to tack "exit 0" onto the end of that output, which would tell the callers to exit. Something like this: diff --git a/parse-options.c b/parse-options.c index a676da86f5..b990f38419 100644 --- a/parse-options.c +++ b/parse-options.c @@ -1473,8 +1473,10 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t } fputc('\n', outfile); - if (!err && ctx && ctx->flags & PARSE_OPT_SHELL_EVAL) + if (!err && ctx && ctx->flags & PARSE_OPT_SHELL_EVAL) { fputs("EOF\n", outfile); + fputs("exit 0\n", outfile); + } return PARSE_OPT_HELP; } And then you don't even need to change the exit code of rev-parse itself (since we'd never hit the "exit $?" that the caller tacks on in case of failure). Though I think it might be reasonable to switch it to 0 anyway. -Peff ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: Unexpected exit code for --help with rev-parse --parseopt 2026-03-15 3:14 ` Jeff King @ 2026-03-15 16:59 ` brian m. carlson 2026-03-15 18:16 ` Jeff King 0 siblings, 1 reply; 14+ messages in thread From: brian m. carlson @ 2026-03-15 16:59 UTC (permalink / raw) To: Jeff King; +Cc: git [-- Attachment #1: Type: text/plain, Size: 1751 bytes --] On 2026-03-15 at 03:14:47, Jeff King wrote: > So the calling program runs that cat command. And I think what you > really want is to tack "exit 0" onto the end of that output, which would > tell the callers to exit. Something like this: > > diff --git a/parse-options.c b/parse-options.c > index a676da86f5..b990f38419 100644 > --- a/parse-options.c > +++ b/parse-options.c > @@ -1473,8 +1473,10 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t > } > fputc('\n', outfile); > > - if (!err && ctx && ctx->flags & PARSE_OPT_SHELL_EVAL) > + if (!err && ctx && ctx->flags & PARSE_OPT_SHELL_EVAL) { > fputs("EOF\n", outfile); > + fputs("exit 0\n", outfile); > + } > > return PARSE_OPT_HELP; > } Yeah, I did some poking around, saw the heredoc, and came to the same conclusion that this was a viable solution. Since we both seem to agree that this is a good solution and it also has the advantage of being backward compatible (in that nobody has to change their code to get the new behaviour[0]), this seems like the best option. > And then you don't even need to change the exit code of rev-parse itself > (since we'd never hit the "exit $?" that the caller tacks on in case of > failure). Though I think it might be reasonable to switch it to 0 > anyway. I can do that as well, even though I think that is actually substantially more complicated than the first part. I'll write up a bunch of new tests for these cases in addition. Thanks for a sober second opinion. [0] As we all know, sometimes one has to use older systems and having scripts break on older systems needlessly is quite inconvenient. -- brian m. carlson (they/them) Toronto, Ontario, CA [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 262 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Unexpected exit code for --help with rev-parse --parseopt 2026-03-15 16:59 ` brian m. carlson @ 2026-03-15 18:16 ` Jeff King 0 siblings, 0 replies; 14+ messages in thread From: Jeff King @ 2026-03-15 18:16 UTC (permalink / raw) To: brian m. carlson; +Cc: git On Sun, Mar 15, 2026 at 04:59:48PM +0000, brian m. carlson wrote: > > And then you don't even need to change the exit code of rev-parse itself > > (since we'd never hit the "exit $?" that the caller tacks on in case of > > failure). Though I think it might be reasonable to switch it to 0 > > anyway. > > I can do that as well, even though I think that is actually > substantially more complicated than the first part. I'll write up a > bunch of new tests for these cases in addition. I would be perfectly happy to leave it as-is. The exit code _shouldn't_ matter anymore if the stdout result (with "exit 0") is being eval'd. So in that case, maybe leaving it as-is might be the more conservative choice, if the caller has somehow screwed up the eval and we want to make sure they still exit. -Peff ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH] rev-parse: have --parseopt callers exit 0 on --help 2026-03-15 0:52 Unexpected exit code for --help with rev-parse --parseopt brian m. carlson 2026-03-15 3:14 ` Jeff King @ 2026-03-16 22:07 ` brian m. carlson 2026-03-17 0:47 ` Junio C Hamano 1 sibling, 1 reply; 14+ messages in thread From: brian m. carlson @ 2026-03-16 22:07 UTC (permalink / raw) To: git; +Cc: Junio C Hamano, Jeff King The standard philosophy for Unix software when a help option (such as --help) is specified is that the software should exit 0, printing the help output to standard output, since the standard output is for user-requested output and the program performed the requested task successfully. If the user specifies an incorrect option, then the help output should be printed to standard error (since the user has made a mistake) and it should exit unsuccessfully. git rev-parse --parseopt properly directs the output in both of these cases, but it currently exits 129 when it receives a --help or -h option on the command line, which causes its invoking script to do the same. This is not in line with the usual behavior and it causes scripts using this command to exit unsuccessfully on --help as well. Note that Git subcommands implemented using scripts, such as git submodule, don't have this problem because Git itself intercepts the --help option and runs man (or a similar tool), which then exits 0. However, this still affects the myriad scripts that use this functionality because Git is widespread and the --parseopt functionality is a good way to get sensible option parsing across shells in a portable way. Because git rev-parse --parseopt is intended to be eval'd by the shell, when help output is to be printed to standard output, Git actually prints a cat command with a heredoc since the standard output is being evaluated by the shell. Thus, to do the right thing, simply add an "exit 0" right after the end of the heredoc, which will cause the invoking program to exit successfully. The usual invocation recommended by the manual page is this: eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)" Thus, the fact that git rev-parse --parseopt still exits 129 in this case is irrelevant, since the "echo exit $?" will print "exit 129", but that will be after the "exit 0" printed by Git—and thus ignored, since the shell will have already exited successfully. Update the tests for this case. Note that we no longer need to delete only the first and last lines in some tests, so add a command to delete the end of the heredoc as well. We could do something clever with sed to delete all but the last two lines or switch to head and tail, but those would be more complicated and less readable, so just stick with the simple approach. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> --- parse-options.c | 2 +- t/t1502-rev-parse-parseopt.sh | 9 +++++++-- t/t1502/optionspec-neg.help | 1 + t/t1502/optionspec.help | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/parse-options.c b/parse-options.c index a676da86f5..85e2f0ea7c 100644 --- a/parse-options.c +++ b/parse-options.c @@ -1474,7 +1474,7 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t fputc('\n', outfile); if (!err && ctx && ctx->flags & PARSE_OPT_SHELL_EVAL) - fputs("EOF\n", outfile); + fputs("EOF\nexit 0\n", outfile); return PARSE_OPT_HELP; } diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh index 3962f1d288..455608c429 100755 --- a/t/t1502-rev-parse-parseopt.sh +++ b/t/t1502-rev-parse-parseopt.sh @@ -12,7 +12,7 @@ check_invalid_long_option () { cat <<-\EOF && error: unknown option `'${opt#--}\'' EOF - sed -e 1d -e \$d <"$TEST_DIRECTORY/t1502/$spec.help" + sed -e 1d -e /EOF/d -e \$d <"$TEST_DIRECTORY/t1502/$spec.help" } >expect && test_expect_code 129 git rev-parse --parseopt -- $opt \ 2>output <"$TEST_DIRECTORY/t1502/$spec" && @@ -87,6 +87,7 @@ test_expect_success 'test --parseopt help output no switches' ' | some-command does foo and bar! | |EOF +|exit 0 END_EXPECT test_expect_code 129 git rev-parse --parseopt -- -h > output < optionspec_no_switches && test_cmp expect output @@ -100,6 +101,7 @@ test_expect_success 'test --parseopt help output hidden switches' ' | some-command does foo and bar! | |EOF +|exit 0 END_EXPECT test_expect_code 129 git rev-parse --parseopt -- -h > output < optionspec_only_hidden_switches && test_cmp expect output @@ -115,6 +117,7 @@ test_expect_success 'test --parseopt help-all output hidden switches' ' | --[no-]hidden1 A hidden switch | |EOF +|exit 0 END_EXPECT test_expect_code 129 git rev-parse --parseopt -- --help-all > output < optionspec_only_hidden_switches && test_cmp expect output @@ -125,7 +128,7 @@ test_expect_success 'test --parseopt invalid switch help output' ' cat <<-\EOF && error: unknown option `does-not-exist'\'' EOF - sed -e 1d -e \$d <"$TEST_DIRECTORY/t1502/optionspec.help" + sed -e 1d -e /EOF/d -e \$d <"$TEST_DIRECTORY/t1502/optionspec.help" } >expect && test_expect_code 129 git rev-parse --parseopt -- --does-not-exist 1>/dev/null 2>output < optionspec && test_cmp expect output @@ -252,6 +255,7 @@ test_expect_success 'test --parseopt help output: "wrapped" options normal "or:" | -h, --help show the help | |EOF + |exit 0 END_EXPECT test_must_fail git rev-parse --parseopt -- -h <spec >actual && @@ -289,6 +293,7 @@ test_expect_success 'test --parseopt help output: multi-line blurb after empty l | -h, --help show the help | |EOF + |exit 0 END_EXPECT test_must_fail git rev-parse --parseopt -- -h <spec >actual && diff --git a/t/t1502/optionspec-neg.help b/t/t1502/optionspec-neg.help index 7a29f8cb03..f85be7b8fd 100644 --- a/t/t1502/optionspec-neg.help +++ b/t/t1502/optionspec-neg.help @@ -10,3 +10,4 @@ usage: some-command [options] <args>... --no-negative cannot be positivated EOF +exit 0 diff --git a/t/t1502/optionspec.help b/t/t1502/optionspec.help index cbdd54d41b..ded35ebc82 100755 --- a/t/t1502/optionspec.help +++ b/t/t1502/optionspec.help @@ -34,3 +34,4 @@ Extras --[no-]extra1 line above used to cause a segfault but no longer does EOF +exit 0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] rev-parse: have --parseopt callers exit 0 on --help 2026-03-16 22:07 ` [PATCH] rev-parse: have --parseopt callers exit 0 on --help brian m. carlson @ 2026-03-17 0:47 ` Junio C Hamano 2026-03-17 11:59 ` brian m. carlson 0 siblings, 1 reply; 14+ messages in thread From: Junio C Hamano @ 2026-03-17 0:47 UTC (permalink / raw) To: brian m. carlson; +Cc: git, Jeff King "brian m. carlson" <sandals@crustytoothpaste.net> writes: > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> > --- > parse-options.c | 2 +- > t/t1502-rev-parse-parseopt.sh | 9 +++++++-- > t/t1502/optionspec-neg.help | 1 + > t/t1502/optionspec.help | 1 + > 4 files changed, 10 insertions(+), 3 deletions(-) Has t1517 passed for you? Queued directly on top of v2.53.0, I am seeing: >>>>> expecting success of 1517.169 ''git instaweb -h' outside a repository': test_expect_code 129 nongit git $cmd -h >usage && test_grep "[Uu]sage: git $cmd " usage test_expect_code: command exited with 0, we wanted 129 nongit git instaweb -h not ok 169 - 'git instaweb -h' outside a repository <<<<< ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rev-parse: have --parseopt callers exit 0 on --help 2026-03-17 0:47 ` Junio C Hamano @ 2026-03-17 11:59 ` brian m. carlson 2026-03-17 14:55 ` Jeff King 0 siblings, 1 reply; 14+ messages in thread From: brian m. carlson @ 2026-03-17 11:59 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Jeff King [-- Attachment #1: Type: text/plain, Size: 1132 bytes --] On 2026-03-17 at 00:47:19, Junio C Hamano wrote: > "brian m. carlson" <sandals@crustytoothpaste.net> writes: > > > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> > > --- > > parse-options.c | 2 +- > > t/t1502-rev-parse-parseopt.sh | 9 +++++++-- > > t/t1502/optionspec-neg.help | 1 + > > t/t1502/optionspec.help | 1 + > > 4 files changed, 10 insertions(+), 3 deletions(-) > > Has t1517 passed for you? > > Queued directly on top of v2.53.0, I am seeing: > > >>>>> > expecting success of 1517.169 ''git instaweb -h' outside a repository': > test_expect_code 129 nongit git $cmd -h >usage && > test_grep "[Uu]sage: git $cmd " usage > > test_expect_code: command exited with 0, we wanted 129 nongit git instaweb -h > not ok 169 - 'git instaweb -h' outside a repository > <<<<< I thought the tests passed, but I may have neglected to run them on the latest revision. Go ahead and drop this for now and I'll send out a v2 either tonight or later this week. My apologies. -- brian m. carlson (they/them) Toronto, Ontario, CA [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 262 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rev-parse: have --parseopt callers exit 0 on --help 2026-03-17 11:59 ` brian m. carlson @ 2026-03-17 14:55 ` Jeff King 2026-03-17 15:07 ` Jeff King 2026-03-17 17:06 ` Junio C Hamano 0 siblings, 2 replies; 14+ messages in thread From: Jeff King @ 2026-03-17 14:55 UTC (permalink / raw) To: brian m. carlson; +Cc: Junio C Hamano, git On Tue, Mar 17, 2026 at 11:59:02AM +0000, brian m. carlson wrote: > On 2026-03-17 at 00:47:19, Junio C Hamano wrote: > > "brian m. carlson" <sandals@crustytoothpaste.net> writes: > > > > > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> > > > --- > > > parse-options.c | 2 +- > > > t/t1502-rev-parse-parseopt.sh | 9 +++++++-- > > > t/t1502/optionspec-neg.help | 1 + > > > t/t1502/optionspec.help | 1 + > > > 4 files changed, 10 insertions(+), 3 deletions(-) > > > > Has t1517 passed for you? > > > > Queued directly on top of v2.53.0, I am seeing: > > > > >>>>> > > expecting success of 1517.169 ''git instaweb -h' outside a repository': > > test_expect_code 129 nongit git $cmd -h >usage && > > test_grep "[Uu]sage: git $cmd " usage > > > > test_expect_code: command exited with 0, we wanted 129 nongit git instaweb -h > > not ok 169 - 'git instaweb -h' outside a repository > > <<<<< > > I thought the tests passed, but I may have neglected to run them on the > latest revision. Go ahead and drop this for now and I'll send out a v2 > either tonight or later this week. My apologies. Hmm. Is this just a matter of tweaking the tests, or is there something bigger going on? These tests are _expecting_ the 129 exit code from most commands. And indeed, "git log -h" produces 129 for example. So it is not just shell scripts using "rev-parse --parseopt" that do this, and those scripts are (currently) consistent with the rest of Git. You'd need something like this (untested) to hit the non-shell commands: diff --git a/parse-options.c b/parse-options.c index 85e2f0ea7c..0ad43ca278 100644 --- a/parse-options.c +++ b/parse-options.c @@ -1197,6 +1197,7 @@ int parse_options(int argc, const char **argv, parse_options_start_1(&ctx, argc, argv, prefix, options, flags); switch (parse_options_step(&ctx, options, usagestr)) { case PARSE_OPT_HELP: + exit(0); case PARSE_OPT_ERROR: exit(129); case PARSE_OPT_COMPLETE: @@ -1495,11 +1496,11 @@ void show_usage_with_options_if_asked(int ac, const char **av, if (!strcmp(av[1], "-h")) { usage_with_options_internal(NULL, usagestr, opts, USAGE_NORMAL, USAGE_TO_STDOUT); - exit(129); + exit(0); } else if (!strcmp(av[1], "--help-all")) { usage_with_options_internal(NULL, usagestr, opts, USAGE_FULL, USAGE_TO_STDOUT); - exit(129); + exit(0); } } } I agree with the general idea that "-h" usually should exit 0. But this is not just a bug fix for --parseopt, but a change in overall intent. It might be worth digging in the commit history or list archive to see if there's any discussion on why we are using 129 in the first place. -Peff ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] rev-parse: have --parseopt callers exit 0 on --help 2026-03-17 14:55 ` Jeff King @ 2026-03-17 15:07 ` Jeff King 2026-03-17 17:06 ` Junio C Hamano 1 sibling, 0 replies; 14+ messages in thread From: Jeff King @ 2026-03-17 15:07 UTC (permalink / raw) To: brian m. carlson; +Cc: Junio C Hamano, git On Tue, Mar 17, 2026 at 10:55:43AM -0400, Jeff King wrote: > I agree with the general idea that "-h" usually should exit 0. But this > is not just a bug fix for --parseopt, but a change in overall intent. It > might be worth digging in the commit history or list archive to see if > there's any discussion on why we are using 129 in the first place. I dug around a little but couldn't find anything conclusive. The first "129" goes back to 2007: https://lore.kernel.org/git/20071013221450.GC2875@steel.home/ But there (and most spots where it is added) it is being used to show options when we have an unknown option. So I _think_ what mostly happened is that we show options in two different scenarios: on an error, and when somebody asks for "-h". And we never differentiated the two, and the latter just inherited the exit code for the former. For example, when you look at ff43ec3e2d (parse-opt: create parse_options_step., 2008-06-23), it introduces: + switch (parse_options_step(&ctx, options, usagestr)) { + case PARSE_OPT_HELP: + exit(129); and only later did we add PARSE_OPT_ERROR to that switch statement. And back then, PARSE_OPT_HELP came only from running usage_with_options(). But I couldn't find any discussion or intentional use of 129 for "-h" output. I do suspect that there may still be some untangling to do. In the earlier (again, untested) patch I showed, I put an exit(0) for that PARSE_OPT_HELP case. But it may be that there's more surgery needed to differentiate "we showed help because of -h" versus "we showed help because you gave a bogus option". -Peff ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rev-parse: have --parseopt callers exit 0 on --help 2026-03-17 14:55 ` Jeff King 2026-03-17 15:07 ` Jeff King @ 2026-03-17 17:06 ` Junio C Hamano 2026-03-17 18:44 ` Jeff King 1 sibling, 1 reply; 14+ messages in thread From: Junio C Hamano @ 2026-03-17 17:06 UTC (permalink / raw) To: Jeff King; +Cc: brian m. carlson, git Jeff King <peff@peff.net> writes: > I agree with the general idea that "-h" usually should exit 0. Yes. > But this > is not just a bug fix for --parseopt, but a change in overall intent. It > might be worth digging in the commit history or list archive to see if > there's any discussion on why we are using 129 in the first place. And if it turns out that old discussion was convincing enough, I'd prefer to see us moving to --help/-h exiting with 0 eventually. I do not mind doing so at the Git 3.0 boundary, if an excuse to make a big change is needed ;-) ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rev-parse: have --parseopt callers exit 0 on --help 2026-03-17 17:06 ` Junio C Hamano @ 2026-03-17 18:44 ` Jeff King 2026-03-18 0:24 ` brian m. carlson 0 siblings, 1 reply; 14+ messages in thread From: Jeff King @ 2026-03-17 18:44 UTC (permalink / raw) To: Junio C Hamano; +Cc: brian m. carlson, git On Tue, Mar 17, 2026 at 10:06:17AM -0700, Junio C Hamano wrote: > > But this > > is not just a bug fix for --parseopt, but a change in overall intent. It > > might be worth digging in the commit history or list archive to see if > > there's any discussion on why we are using 129 in the first place. > > And if it turns out that old discussion was convincing enough, I'd > prefer to see us moving to --help/-h exiting with 0 eventually. I > do not mind doing so at the Git 3.0 boundary, if an excuse to make > a big change is needed ;-) I could not find anything convincing. :) We should also apply our little grey cells and see if we can think of any reason somebody would be unhappy with a change of exit code now. The most I could come up with is a script like: #!/bin/sh git rev-list "$@" >tmp && do_something <tmp where you might imagine it is run as "foo.sh --objects HEAD" or something. Right now, running: foo.sh -h will bail when rev-list returns 129, but in the proposed world it would keep going and run do_something. And you can further imagine a world where the script then quietly produces the wrong answer, because do_something thinks the rev-list output was empty (or actually it is worse; it gets the help output here). I think this is mostly a case of "if it hurts, don't do it". The "-h" is not doing anything useful (the user does not even see the help text!), and if the script wants to support a usage message, it should parse the "-h" out separately. Could somebody maliciously convince you to pass "-h" to such a script? Maybe, but not only are we getting into a series of increasingly unlikely events, but I think that means you probably have worse option-injection risks. So unless somebody can come up with a more compelling example, I don't really see much backwards-compatibility risk. But maybe I just lack imagination. ;) -Peff ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rev-parse: have --parseopt callers exit 0 on --help 2026-03-17 18:44 ` Jeff King @ 2026-03-18 0:24 ` brian m. carlson 2026-03-18 1:22 ` Jeff King 0 siblings, 1 reply; 14+ messages in thread From: brian m. carlson @ 2026-03-18 0:24 UTC (permalink / raw) To: Jeff King; +Cc: Junio C Hamano, git [-- Attachment #1: Type: text/plain, Size: 1571 bytes --] On 2026-03-17 at 18:44:41, Jeff King wrote: > So unless somebody can come up with a more compelling example, I don't > really see much backwards-compatibility risk. But maybe I just lack > imagination. ;) The only reason I can imagine intentionally using `-h` in a script is to find out whether an option is supported. For instance, I have this alias: co = "!f() { if git checkout -h | grep -qs recurse-submodules; \ then git checkout --recurse-submodules \"$@\"; \ else git checkout \"$@\" && git sui; \ fi; };f" (`sui` is `submodule update --init`.) In most cases, that's going to be upstream of a pipe, so unless you're using `-o pipefail` (which is only in POSIX in POSIX 1003.1-2024), it's going to succeed anyway. I suppose one can also use it to generate a manual page, which manual page generators do, but that seems silly when Git provides much better ones unless you desperately need one in a different language for which Git has translations but no manual page. None of these seem like they're likely to care about the exit status and I suspect that if they do, they are probably using `|| true` to ignore the unexpected 129 exit code. So I agree that there's unlikely to be any sort of backward compatibility issues. If the consensus is that this is shipped only in 3.0, then we can do that, but I think many people are not going to care and those that do will welcome the change, so I'd just rather treat it as a bug that we fix. -- brian m. carlson (they/them) Toronto, Ontario, CA [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 262 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rev-parse: have --parseopt callers exit 0 on --help 2026-03-18 0:24 ` brian m. carlson @ 2026-03-18 1:22 ` Jeff King 2026-03-18 2:45 ` Junio C Hamano 0 siblings, 1 reply; 14+ messages in thread From: Jeff King @ 2026-03-18 1:22 UTC (permalink / raw) To: brian m. carlson; +Cc: Junio C Hamano, git On Wed, Mar 18, 2026 at 12:24:38AM +0000, brian m. carlson wrote: > None of these seem like they're likely to care about the exit status and > I suspect that if they do, they are probably using `|| true` to ignore > the unexpected 129 exit code. Yeah, I'd venture to say that moving from 129 to 0 would be a strict improvement for the cases you outlined. > So I agree that there's unlikely to be any sort of backward > compatibility issues. If the consensus is that this is shipped only in > 3.0, then we can do that, but I think many people are not going to care > and those that do will welcome the change, so I'd just rather treat it > as a bug that we fix. Nah, I think everything I have seen points to treating this as a simple improvement / fix that we can do in the regular way. -Peff ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rev-parse: have --parseopt callers exit 0 on --help 2026-03-18 1:22 ` Jeff King @ 2026-03-18 2:45 ` Junio C Hamano 0 siblings, 0 replies; 14+ messages in thread From: Junio C Hamano @ 2026-03-18 2:45 UTC (permalink / raw) To: Jeff King; +Cc: brian m. carlson, git Jeff King <peff@peff.net> writes: > On Wed, Mar 18, 2026 at 12:24:38AM +0000, brian m. carlson wrote: > >> None of these seem like they're likely to care about the exit status and >> I suspect that if they do, they are probably using `|| true` to ignore >> the unexpected 129 exit code. > > Yeah, I'd venture to say that moving from 129 to 0 would be a strict > improvement for the cases you outlined. > >> So I agree that there's unlikely to be any sort of backward >> compatibility issues. If the consensus is that this is shipped only in >> 3.0, then we can do that, but I think many people are not going to care >> and those that do will welcome the change, so I'd just rather treat it >> as a bug that we fix. > > Nah, I think everything I have seen points to treating this as a simple > improvement / fix that we can do in the regular way. I 100% agree. The message I earlier wrote (which contained the mention of Git 3.0) lacked "even" before an "if". ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-03-18 2:45 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-15 0:52 Unexpected exit code for --help with rev-parse --parseopt brian m. carlson 2026-03-15 3:14 ` Jeff King 2026-03-15 16:59 ` brian m. carlson 2026-03-15 18:16 ` Jeff King 2026-03-16 22:07 ` [PATCH] rev-parse: have --parseopt callers exit 0 on --help brian m. carlson 2026-03-17 0:47 ` Junio C Hamano 2026-03-17 11:59 ` brian m. carlson 2026-03-17 14:55 ` Jeff King 2026-03-17 15:07 ` Jeff King 2026-03-17 17:06 ` Junio C Hamano 2026-03-17 18:44 ` Jeff King 2026-03-18 0:24 ` brian m. carlson 2026-03-18 1:22 ` Jeff King 2026-03-18 2:45 ` Junio C Hamano
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox