All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] help: prompt user to run corrected command on typo
@ 2026-06-18 14:26 calicomills
  2026-06-18 17:48 ` Justin Tobler
  0 siblings, 1 reply; 6+ messages in thread
From: calicomills @ 2026-06-18 14:26 UTC (permalink / raw)
  To: git; +Cc: gitster

From 0dc9e5c4593611b75e7003e8fdbea9370524c05b Mon Sep 17 00:00:00 2001
From: calicomills <jishnuck26@gmail.com>
Date: Thu, 18 Jun 2026 19:47:12 +0530
Subject: [PATCH] help: prompt user to run corrected command on typo

When a user mistypes a git command and there is exactly one similar
command, git currently prints a suggestion but exits, requiring the
user to retype the corrected command manually.

Instead, when stdin and stderr are both connected to a terminal and
there is a single best match, prompt the user with:

  Did you mean 'git checkout neo'? [y/N]

The full corrected invocation (command + original arguments) is shown
in the prompt so the user knows exactly what will run. Answering 'y'
re-executes git with the corrected command and all original arguments.
Answering anything else exits as before.

When there are multiple similarly-named commands, or when running
non-interactively (scripts, pipes), the original behaviour of printing
the suggestion list and exiting is preserved.

The help_unknown_cmd() signature is updated to accept the full args
vector so the prompt can include the original arguments alongside the
corrected command name.

Add tests to t9003 covering:
- non-interactive single match: falls back to suggestion list
- non-interactive multiple matches: falls back to suggestion list
- interactive single match, 'y': corrected command runs (TTY prereq)
- interactive single match, 'n': exits cleanly (TTY prereq)

Signed-off-by: calicomills <jishnuck26@gmail.com>
---
 builtin/help.c              |  2 +-
 git.c                       |  2 +-
 help.c                      | 40 ++++++++++++++++++++++------
 help.h                      |  3 ++-
 t/t9003-help-autocorrect.sh | 53 +++++++++++++++++++++++++++++++++++++
 5 files changed, 89 insertions(+), 11 deletions(-)

diff --git a/builtin/help.c b/builtin/help.c
index a140339999..b17e61ccc8 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -618,7 +618,7 @@ static char *check_git_cmd(const char *cmd)
 	}
 
 	if (exclude_guides)
-		return help_unknown_cmd(cmd);
+		return help_unknown_cmd(cmd, NULL);
 
 	return xstrdup(cmd);
 }
diff --git a/git.c b/git.c
index 36f08891ef..d379cc85bb 100644
--- a/git.c
+++ b/git.c
@@ -994,7 +994,7 @@ int cmd_main(int argc, const char **argv)
 			exit(1);
 		}
 		if (!done_help) {
-			char *assumed = help_unknown_cmd(cmd);
+			char *assumed = help_unknown_cmd(cmd, &args);
 			strvec_replace(&args, 0, assumed);
 			free(assumed);
 			cmd = args.v[0];
diff --git a/help.c b/help.c
index 46241492ce..30f32a7206 100644
--- a/help.c
+++ b/help.c
@@ -641,7 +641,7 @@ static const char bad_interpreter_advice[] =
 	N_("'%s' appears to be a git command, but we were not\n"
 	"able to execute it. Maybe git-%s is broken?");
 
-char *help_unknown_cmd(const char *cmd)
+char *help_unknown_cmd(const char *cmd, const struct strvec *args)
 {
 	struct help_unknown_cmd_config cfg = { 0 };
 	int i, n, best_similarity = 0;
@@ -762,13 +762,37 @@ char *help_unknown_cmd(const char *cmd)
 	fprintf_ln(stderr, _("git: '%s' is not a git command. See 'git --help'."), cmd);
 
 	if (SIMILAR_ENOUGH(best_similarity)) {
-		fprintf_ln(stderr,
-			   Q_("\nThe most similar command is",
-			      "\nThe most similar commands are",
-			   n));
-
-		for (i = 0; i < n; i++)
-			fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
+		if (n == 1 && isatty(0) && isatty(2)) {
+			char *answer;
+			struct strbuf msg = STRBUF_INIT;
+			struct strbuf full_cmd = STRBUF_INIT;
+			strbuf_addstr(&full_cmd, main_cmds.names[0]->name);
+			if (args) {
+				for (size_t j = 1; j < args->nr; j++) {
+					strbuf_addch(&full_cmd, ' ');
+					strbuf_addstr(&full_cmd, args->v[j]);
+				}
+			}
+			strbuf_addf(&msg, _("\nDid you mean 'git %s'? [y/N] "),
+				    full_cmd.buf);
+			strbuf_release(&full_cmd);
+			answer = git_prompt(msg.buf, PROMPT_ECHO);
+			strbuf_release(&msg);
+			if (starts_with(answer, "y") || starts_with(answer, "Y")) {
+				char *assumed = xstrdup(main_cmds.names[0]->name);
+				cmdnames_release(&cfg.aliases);
+				cmdnames_release(&main_cmds);
+				cmdnames_release(&other_cmds);
+				return assumed;
+			}
+		} else {
+			fprintf_ln(stderr,
+				   Q_("\nThe most similar command is",
+				      "\nThe most similar commands are",
+				   n));
+			for (i = 0; i < n; i++)
+				fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
+		}
 	}
 
 	exit(1);
diff --git a/help.h b/help.h
index c54bf0977d..a8c465b3df 100644
--- a/help.h
+++ b/help.h
@@ -32,7 +32,8 @@ void list_all_other_cmds(struct string_list *list);
 void list_cmds_by_category(struct string_list *list,
 			   const char *category);
 void list_cmds_by_config(struct string_list *list);
-char *help_unknown_cmd(const char *cmd);
+#include "strvec.h"
+char *help_unknown_cmd(const char *cmd, const struct strvec *args);
 void load_command_list(const char *prefix,
 		       struct cmdnames *main_cmds,
 		       struct cmdnames *other_cmds);
diff --git a/t/t9003-help-autocorrect.sh b/t/t9003-help-autocorrect.sh
index 8da318d2b5..6fe2da1595 100755
--- a/t/t9003-help-autocorrect.sh
+++ b/t/t9003-help-autocorrect.sh
@@ -70,4 +70,57 @@ test_expect_success 'autocorrect works in work tree created from bare repo' '
 	git -C worktree -c help.autocorrect=immediate status
 '
 
+# Default behaviour (no help.autocorrect set): when there is exactly one
+# similar command but the session is non-interactive, fall back to printing
+# the suggestion list and exiting rather than showing a prompt.
+test_expect_success 'default: single match non-interactive shows suggestion and fails' '
+	test_might_fail git config --unset help.autocorrect &&
+
+	test_must_fail git lfg 2>actual &&
+	grep "most similar command" actual &&
+	grep "lgf" actual
+'
+
+test_expect_success 'default: multiple matches non-interactive shows list and fails' '
+	test_might_fail git config --unset help.autocorrect &&
+
+	test_must_fail git com 2>actual &&
+	grep "most similar commands" actual &&
+	grep "commit" actual
+'
+
+# Interactive prompt tests require a real TTY.  On macOS the TTY prereq is
+# skipped due to IO::Pty reliability issues; these tests run on Linux CI.
+test_expect_success TTY 'default: single match interactive, answer y runs command' '
+	git config --unset help.autocorrect &&
+
+	write_script git-typotest <<-\EOF &&
+		echo typotest-ran
+	EOF
+	PATH="$PATH:." export PATH &&
+
+	# Feed "y" to /dev/tty via a wrapper that answers the prompt
+	write_script answer-prompt <<-\EOF &&
+		# Write the answer to the controlling terminal
+		printf "y\n" >/dev/tty
+		exec "$@"
+	EOF
+
+	test_terminal ./answer-prompt git typotest 2>err >out &&
+	grep "typotest-ran" out &&
+	grep "Did you mean" err
+'
+
+test_expect_success TTY 'default: single match interactive, answer n exits cleanly' '
+	git config --unset help.autocorrect &&
+
+	write_script answer-prompt-no <<-\EOF &&
+		printf "n\n" >/dev/tty
+		exec "$@"
+	EOF
+
+	test_must_fail test_terminal ./answer-prompt-no git typotest 2>err &&
+	grep "Did you mean" err
+'
+
 test_done
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] help: prompt user to run corrected command on typo
  2026-06-18 14:26 [PATCH] help: prompt user to run corrected command on typo calicomills
@ 2026-06-18 17:48 ` Justin Tobler
  2026-06-19  6:05   ` Jishnu C K
  2026-06-19 17:04   ` [PATCH v2] help: include arguments in autocorrect=prompt message Jishnu C K
  0 siblings, 2 replies; 6+ messages in thread
From: Justin Tobler @ 2026-06-18 17:48 UTC (permalink / raw)
  To: calicomills; +Cc: git, gitster

On 26/06/18 07:26AM, calicomills wrote:
> From 0dc9e5c4593611b75e7003e8fdbea9370524c05b Mon Sep 17 00:00:00 2001
> From: calicomills <jishnuck26@gmail.com>
> Date: Thu, 18 Jun 2026 19:47:12 +0530
> Subject: [PATCH] help: prompt user to run corrected command on typo
> 
> When a user mistypes a git command and there is exactly one similar
> command, git currently prints a suggestion but exits, requiring the
> user to retype the corrected command manually.
> 
> Instead, when stdin and stderr are both connected to a terminal and
> there is a single best match, prompt the user with:
> 
>   Did you mean 'git checkout neo'? [y/N]
> 
> The full corrected invocation (command + original arguments) is shown
> in the prompt so the user knows exactly what will run. Answering 'y'
> re-executes git with the corrected command and all original arguments.
> Answering anything else exits as before.

Isn't this already possible via setting `help.autoCorrect=prompt` in the
config? For example:

  git -c help.autoCorrect=prompt comit --allow-empty -m init

seems to already do exactly what is proposed here.

-Justin

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] help: prompt user to run corrected command on typo
  2026-06-18 17:48 ` Justin Tobler
@ 2026-06-19  6:05   ` Jishnu C K
  2026-06-19 16:24     ` Justin Tobler
  2026-06-19 16:37     ` Junio C Hamano
  2026-06-19 17:04   ` [PATCH v2] help: include arguments in autocorrect=prompt message Jishnu C K
  1 sibling, 2 replies; 6+ messages in thread
From: Jishnu C K @ 2026-06-19  6:05 UTC (permalink / raw)
  To: Justin Tobler; +Cc: git, gitster

On Thu, Jun 18, 2026, Justin Tobler wrote:
> Isn't this already possible via setting `help.autoCorrect=prompt` in the
> config?

Thank you for the review.

You're right that `help.autocorrect=prompt` exists and is similar.
Our change differs in two ways:

1. No configuration needed. The existing prompt mode requires the user
   to explicitly set `help.autocorrect=prompt`. Most users are unaware
   of this option, so they see a suggestion and must retype the full
   command manually. Our change makes the interactive prompt the
   default behaviour when stdin and stderr are a terminal.

2. The prompt includes the original arguments. `help.autocorrect=prompt`
   shows only:

     Run 'checkout' instead [y/N]?

   Our prompt shows the full corrected invocation:

     Did you mean 'git checkout neo'? [y/N]

   This lets the user confirm exactly what will run, including their
   original arguments, before pressing 'y'.

If the consensus is that the default should remain non-interactive,
we are happy to rework this as an improvement to the existing
`autocorrect=prompt` mode (showing args in the prompt) with
documentation updates to make the option more discoverable.

-- 
Jishnu C K

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] help: prompt user to run corrected command on typo
  2026-06-19  6:05   ` Jishnu C K
@ 2026-06-19 16:24     ` Justin Tobler
  2026-06-19 16:37     ` Junio C Hamano
  1 sibling, 0 replies; 6+ messages in thread
From: Justin Tobler @ 2026-06-19 16:24 UTC (permalink / raw)
  To: Jishnu C K; +Cc: git, gitster

On 26/06/18 11:05PM, Jishnu C K wrote:
> If the consensus is that the default should remain non-interactive,
> we are happy to rework this as an improvement to the existing
> `autocorrect=prompt` mode (showing args in the prompt) with
> documentation updates to make the option more discoverable.

I'm not sure what the current consensus is here, but as it would be a
change to the existing behavior it would need its merits discussed
accordingly. Personally, I think requiring users to opt-in to
autocorrect isn't a significant barrier itself. It does require that
users know that the option is available in the first place though. So if
discoverablility of this feature is lacking and can be improved in
documentation, that certainly seems like a reasonable change. 

Regarding changing the prompt to display command arguments, I'm
relatively indifferent towards it. I'm not sure it adds a ton of value,
but maybe other folks will have a different opinion.

-Justin

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] help: prompt user to run corrected command on typo
  2026-06-19  6:05   ` Jishnu C K
  2026-06-19 16:24     ` Justin Tobler
@ 2026-06-19 16:37     ` Junio C Hamano
  1 sibling, 0 replies; 6+ messages in thread
From: Junio C Hamano @ 2026-06-19 16:37 UTC (permalink / raw)
  To: Jishnu C K; +Cc: Justin Tobler, git

Jishnu C K <jishnuck26@gmail.com> writes:

> You're right that `help.autocorrect=prompt` exists and is similar.
> Our change differs in two ways:
>
> 1. No configuration needed. The existing prompt mode requires the user

I do not particularly see it as an advantage.

> 2. The prompt includes the original arguments. `help.autocorrect=prompt`
>    shows only:
>
>      Run 'checkout' instead [y/N]?
>
>    Our prompt shows the full corrected invocation:
>
>      Did you mean 'git checkout neo'? [y/N]
>
>    This lets the user confirm exactly what will run, including their
>    original arguments, before pressing 'y'.

This may be an improvement, but is there a reason why such a change
must be done as a parallel and unrelated (re)implementation and not
as an incrementa improvement to the code that implements the
existing feature?




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2] help: include arguments in autocorrect=prompt message
  2026-06-18 17:48 ` Justin Tobler
  2026-06-19  6:05   ` Jishnu C K
@ 2026-06-19 17:04   ` Jishnu C K
  1 sibling, 0 replies; 6+ messages in thread
From: Jishnu C K @ 2026-06-19 17:04 UTC (permalink / raw)
  To: git; +Cc: gitster, Justin Tobler

v2: Reworked as an incremental improvement to the existing
autocorrect=prompt code path rather than a parallel reimplementation,
per feedback from Junio and Justin.

---
From a4e8fb6fd6dd6a501e565c7500cbf927d7cb0b42 Mon Sep 17 00:00:00 2001
From: calicomills <jishnuck26@gmail.com>
Date: Fri, 19 Jun 2026 13:01:40 +0530
Subject: [PATCH v2 v2] help: include arguments in autocorrect=prompt message

When 'help.autocorrect=prompt' is configured and the user mistypes
a git command, the prompt currently shows only the corrected command
name:

  Run 'checkout' instead [y/N]?

This leaves the user unsure whether their original arguments will be
preserved. Update the prompt to include the full corrected invocation:

  Run 'git checkout neo' instead [y/N]?

The help_unknown_cmd() signature is updated to accept the args vector
so the prompt can show the original arguments alongside the corrected
command name. Callers that do not have access to the args (e.g.
builtin/help.c) pass NULL, which is handled gracefully.

Signed-off-by: calicomills <jishnuck26@gmail.com>
---
 help.c                      | 49 +++++++++++++----------------------
 t/t9003-help-autocorrect.sh | 51 +++++--------------------------------
 2 files changed, 23 insertions(+), 77 deletions(-)

diff --git a/help.c b/help.c
index 30f32a7206..9ea4c076e1 100644
--- a/help.c
+++ b/help.c
@@ -739,7 +739,16 @@ char *help_unknown_cmd(const char *cmd, const struct strvec *args)
 		else if (cfg.autocorrect == AUTOCORRECT_PROMPT) {
 			char *answer;
 			struct strbuf msg = STRBUF_INIT;
-			strbuf_addf(&msg, _("Run '%s' instead [y/N]? "), assumed);
+			struct strbuf full_cmd = STRBUF_INIT;
+			strbuf_addstr(&full_cmd, assumed);
+			if (args) {
+				for (size_t j = 1; j < args->nr; j++) {
+					strbuf_addch(&full_cmd, ' ');
+					strbuf_addstr(&full_cmd, args->v[j]);
+				}
+			}
+			strbuf_addf(&msg, _("Run 'git %s' instead [y/N]? "), full_cmd.buf);
+			strbuf_release(&full_cmd);
 			answer = git_prompt(msg.buf, PROMPT_ECHO);
 			strbuf_release(&msg);
 			if (!(starts_with(answer, "y") ||
@@ -762,37 +771,13 @@ char *help_unknown_cmd(const char *cmd, const struct strvec *args)
 	fprintf_ln(stderr, _("git: '%s' is not a git command. See 'git --help'."), cmd);
 
 	if (SIMILAR_ENOUGH(best_similarity)) {
-		if (n == 1 && isatty(0) && isatty(2)) {
-			char *answer;
-			struct strbuf msg = STRBUF_INIT;
-			struct strbuf full_cmd = STRBUF_INIT;
-			strbuf_addstr(&full_cmd, main_cmds.names[0]->name);
-			if (args) {
-				for (size_t j = 1; j < args->nr; j++) {
-					strbuf_addch(&full_cmd, ' ');
-					strbuf_addstr(&full_cmd, args->v[j]);
-				}
-			}
-			strbuf_addf(&msg, _("\nDid you mean 'git %s'? [y/N] "),
-				    full_cmd.buf);
-			strbuf_release(&full_cmd);
-			answer = git_prompt(msg.buf, PROMPT_ECHO);
-			strbuf_release(&msg);
-			if (starts_with(answer, "y") || starts_with(answer, "Y")) {
-				char *assumed = xstrdup(main_cmds.names[0]->name);
-				cmdnames_release(&cfg.aliases);
-				cmdnames_release(&main_cmds);
-				cmdnames_release(&other_cmds);
-				return assumed;
-			}
-		} else {
-			fprintf_ln(stderr,
-				   Q_("\nThe most similar command is",
-				      "\nThe most similar commands are",
-				   n));
-			for (i = 0; i < n; i++)
-				fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
-		}
+		fprintf_ln(stderr,
+			   Q_("\nThe most similar command is",
+			      "\nThe most similar commands are",
+			   n));
+
+		for (i = 0; i < n; i++)
+			fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
 	}
 
 	exit(1);
diff --git a/t/t9003-help-autocorrect.sh b/t/t9003-help-autocorrect.sh
index 6fe2da1595..75821d63e1 100755
--- a/t/t9003-help-autocorrect.sh
+++ b/t/t9003-help-autocorrect.sh
@@ -70,57 +70,18 @@ test_expect_success 'autocorrect works in work tree created from bare repo' '
 	git -C worktree -c help.autocorrect=immediate status
 '
 
-# Default behaviour (no help.autocorrect set): when there is exactly one
-# similar command but the session is non-interactive, fall back to printing
-# the suggestion list and exiting rather than showing a prompt.
-test_expect_success 'default: single match non-interactive shows suggestion and fails' '
-	test_might_fail git config --unset help.autocorrect &&
-
-	test_must_fail git lfg 2>actual &&
-	grep "most similar command" actual &&
-	grep "lgf" actual
-'
-
-test_expect_success 'default: multiple matches non-interactive shows list and fails' '
-	test_might_fail git config --unset help.autocorrect &&
-
-	test_must_fail git com 2>actual &&
-	grep "most similar commands" actual &&
-	grep "commit" actual
-'
-
-# Interactive prompt tests require a real TTY.  On macOS the TTY prereq is
-# skipped due to IO::Pty reliability issues; these tests run on Linux CI.
-test_expect_success TTY 'default: single match interactive, answer y runs command' '
-	git config --unset help.autocorrect &&
-
-	write_script git-typotest <<-\EOF &&
-		echo typotest-ran
-	EOF
-	PATH="$PATH:." export PATH &&
-
-	# Feed "y" to /dev/tty via a wrapper that answers the prompt
-	write_script answer-prompt <<-\EOF &&
-		# Write the answer to the controlling terminal
-		printf "y\n" >/dev/tty
-		exec "$@"
-	EOF
-
-	test_terminal ./answer-prompt git typotest 2>err >out &&
-	grep "typotest-ran" out &&
-	grep "Did you mean" err
-'
-
-test_expect_success TTY 'default: single match interactive, answer n exits cleanly' '
-	git config --unset help.autocorrect &&
+# autocorrect=prompt should include the original arguments in the prompt.
+# Requires a TTY; skipped on macOS due to IO::Pty reliability issues.
+test_expect_success TTY 'autocorrect=prompt includes arguments in prompt' '
+	git config help.autocorrect prompt &&
 
 	write_script answer-prompt-no <<-\EOF &&
 		printf "n\n" >/dev/tty
 		exec "$@"
 	EOF
 
-	test_must_fail test_terminal ./answer-prompt-no git typotest 2>err &&
-	grep "Did you mean" err
+	test_must_fail test_terminal ./answer-prompt-no git lfg --oneline 2>actual &&
+	grep "lgf --oneline" actual
 '
 
 test_done
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-06-19 17:04 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-18 14:26 [PATCH] help: prompt user to run corrected command on typo calicomills
2026-06-18 17:48 ` Justin Tobler
2026-06-19  6:05   ` Jishnu C K
2026-06-19 16:24     ` Justin Tobler
2026-06-19 16:37     ` Junio C Hamano
2026-06-19 17:04   ` [PATCH v2] help: include arguments in autocorrect=prompt message Jishnu C K

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.