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.
Most of our commands currently exit 129 on receiving the -h option to
print the short help, which does not line up with the standard
philosophy above. Let's change that to exit 0 instead.
This requires changes to a variety of tests which previously wanted the
129 exit code, so update them. Note that because git diff does its own
option parsing, it still exits with 129, so update some of the tests to
expect either exit status.
Some commands also now pass with -h but not --help-all, so handle those
cases differently for those commands.
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
brian m. carlson committedJul 8, 2026 at 00:15 UTCcdaf12f762855b293829ccf540698f86ccb9655e
37 files changed+85-71
builtin/blame.c
+1
index 65d43c7d48..38749f79c2 100644--- a/builtin/blame.c+++ b/builtin/blame.c@@ -1013,6 +1013,7 @@ int cmd_blame(int argc, case PARSE_OPT_UNKNOWN: break; case PARSE_OPT_HELP:+ exit(0); case PARSE_OPT_HELP_ERROR: case PARSE_OPT_ERROR: case PARSE_OPT_SUBCOMMAND:
builtin/shortlog.c
+1
index cd262bd376..4c78d2e5ba 100644--- a/builtin/shortlog.c+++ b/builtin/shortlog.c@@ -433,6 +433,7 @@ int cmd_shortlog(int argc, case PARSE_OPT_UNKNOWN: break; case PARSE_OPT_HELP:+ exit(0); case PARSE_OPT_HELP_ERROR: case PARSE_OPT_ERROR: case PARSE_OPT_SUBCOMMAND:
builtin/update-index.c
+1
index ac4610ec94..6810327209 100644--- a/builtin/update-index.c+++ b/builtin/update-index.c@@ -1133,6 +1133,7 @@ int cmd_update_index(int argc, break; switch (parseopt_state) { case PARSE_OPT_HELP:+ exit(0); case PARSE_OPT_HELP_ERROR: case PARSE_OPT_ERROR: exit(129);
contrib/subtree/t/t7900-subtree.sh
+1-1
index 4194687cfb..c10f283b38 100755--- a/contrib/subtree/t/t7900-subtree.sh+++ b/contrib/subtree/t/t7900-subtree.sh@@ -99,7 +99,7 @@ test_create_subtree_add () { } test_expect_success 'shows short help text for -h' '- test_expect_code 129 git subtree -h >out 2>err &&+ git subtree -h >out 2>err && test_must_be_empty err && grep -e "^ *or: git subtree pull" out && grep -F -e "--[no-]annotate" out
parse-options.c
+8-3
index cc3a8b0fe3..08c21d9fc0 100644--- a/parse-options.c+++ b/parse-options.c@@ -1135,8 +1135,9 @@ enum parse_opt_result parse_options_step(struct parse_opt_ctx_t *ctx, case PARSE_OPT_UNKNOWN: goto unknown; case PARSE_OPT_HELP:- case PARSE_OPT_HELP_ERROR: goto show_usage;+ case PARSE_OPT_HELP_ERROR:+ goto show_usage_stderr; case PARSE_OPT_NON_OPTION: case PARSE_OPT_SUBCOMMAND: case PARSE_OPT_COMPLETE:@@ -1170,6 +1171,9 @@ unknown: show_usage: return usage_with_options_internal(ctx, usagestr, options, USAGE_NORMAL, USAGE_TO_STDOUT);+ show_usage_stderr:+ return usage_with_options_internal(ctx, usagestr, options,+ USAGE_NORMAL, USAGE_TO_STDERR); } int parse_options_end(struct parse_opt_ctx_t *ctx)@@ -1201,6 +1205,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_HELP_ERROR: case PARSE_OPT_ERROR: exit(129);@@ -1500,11 +1505,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); } } }
t/for-each-ref-tests.sh
+1-1
index bd2d45c971..b95e5b6ca0 100644--- a/t/for-each-ref-tests.sh+++ b/t/for-each-ref-tests.sh@@ -522,7 +522,7 @@ test_expect_success 'Verify descending sort' ' ' test_expect_success 'Give help even with invalid sort atoms' '- test_expect_code 129 ${git_for_each_ref} --sort=bogus -h >actual 2>&1 &&+ ${git_for_each_ref} --sort=bogus -h >actual 2>&1 && grep "^usage: ${git_for_each_ref}" actual '
t/t0012-help.sh
+1-1
index c33501bdcd..7815ff14f2 100755--- a/t/t0012-help.sh+++ b/t/t0012-help.sh@@ -260,7 +260,7 @@ do ( GIT_CEILING_DIRECTORIES=$(pwd) && export GIT_CEILING_DIRECTORIES &&- test_expect_code 129 git -C sub $builtin -h >output 2>err+ git -C sub $builtin -h >output 2>err ) && test_must_be_empty err && test_grep usage output
index 0132e772e4..2ea9fa13c5 100755--- a/t/t1800-hook.sh+++ b/t/t1800-hook.sh@@ -75,10 +75,10 @@ sentinel_detector () { test_expect_success 'git hook usage' ' test_expect_code 129 git hook && test_expect_code 129 git hook run &&- test_expect_code 129 git hook run -h &&+ git hook run -h && test_expect_code 129 git hook run --unknown 2>err && test_expect_code 129 git hook list &&- test_expect_code 129 git hook list -h &&+ git hook list -h && grep "unknown option" err '
t/t1900-repo-info.sh
+1-1
index 39bb77dda0..826686955d 100755--- a/t/t1900-repo-info.sh+++ b/t/t1900-repo-info.sh@@ -150,7 +150,7 @@ test_expect_success 'git repo info --keys uses lines as its default output forma ' test_expect_success 'git repo info -h shows only repo info usage' '- test_must_fail git repo info -h >actual &&+ git repo info -h >actual && test_grep "git repo info" actual && test_grep ! "git repo structure" actual '