"git describe --exact-match X" is designed to fail when no tags are pointing at X. When given "--no-exact-match", the command line parser did the same thing as "--exact-match", which was clearly bogus. What "--no-exact-match" should do is not entirely clear, though. Internally, there is an integer "max-candidates" that specifies how many possible "describe" names are computed (among which, the best name is picked), and this limit is set to 10 by default. The "--candidates=<number>" option sets it to an arbitrary number (the idea being that by spending a bit more computing resource, we might be able to come up with a better name). "--exact-match" uses this mechanism to express that the user refuses to accept a name that is any non-zero distance away from a tag, and it does so by setting the limit to 0. Making "--no-exact-match" reset the counter to its default value would allow "git describe --exact-match --no-exact-match X" to defeat the earlier "--exact-match", and that is the solution we adopt here in this patch. However, it is not clear what should happen in this command: git describe --exact-match --candidates=20 --no-exact-match X Saying --candidates=20 allows us to go inexact, but then should "--no-exact-match" become a no-op? The implementation in this patch resets the counter to its default value, defeating the earlier setting done by the "--candidates" option. We probably could solve it by introducing an extra variable and combining the two after parse_options() returns, but let's declare that it is not worth solving and use the simpler solution, i.e. "--no-exact-match" resets the limit to its default value. The "--no-exact-match" option was not covered in the tests, so let's add a few. Also add a case where --exact-match option is used on a commit that cannot be described without distance from tags and make sure the command fails. Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- builtin/describe.c | 11 ++++++++--- t/t6120-describe.sh | 8 ++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/builtin/describe.c b/builtin/describe.c index 55b4baaa22..879f8a8d45 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -34,13 +34,15 @@ static const char * const describe_usage[] = { NULL }; +#define DEFAULT_MAX_CANDIATES 10 + static int debug; /* Display lots of verbose info */ static int all; /* Any valid ref can be used */ static int tags; /* Allow lightweight tags */ static int longformat; static int first_parent; static int abbrev = -1; /* unspecified */ -static int max_candidates = 10; +static int max_candidates = DEFAULT_MAX_CANDIATES; static struct hashmap names; static int have_util; static struct string_list patterns = STRING_LIST_INIT_NODUP; @@ -567,8 +569,11 @@ int cmd_describe(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "long", &longformat, N_("always use long format")), OPT_BOOL(0, "first-parent", &first_parent, N_("only follow first parent")), OPT__ABBREV(&abbrev), - OPT_SET_INT(0, "exact-match", &max_candidates, - N_("only output exact matches"), 0), + OPT_SET_INT_F(0, "exact-match", &max_candidates, + N_("only output exact matches"), 0, PARSE_OPT_NONEG), + OPT_SET_INT_F(0, "no-exact-match", &max_candidates, + N_("only output exact matches"), DEFAULT_MAX_CANDIATES, + PARSE_OPT_NONEG), OPT_INTEGER(0, "candidates", &max_candidates, N_("consider <n> most recent tags (default: 10)")), OPT_STRING_LIST(0, "match", &patterns, N_("pattern"), diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index c9afcef201..0a5c487540 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -85,6 +85,7 @@ check_describe e-1-gHASH --tags HEAD^^ check_describe c-2-gHASH --tags HEAD^^2 check_describe B --tags HEAD^^2^ check_describe e --tags HEAD^^^ +check_describe e --tags --exact-match HEAD^^^ check_describe heads/main --all HEAD check_describe tags/c-6-gHASH --all HEAD^ @@ -96,6 +97,13 @@ check_describe A-3-gHASH --long HEAD^^2 check_describe c-7-gHASH --tags check_describe e-3-gHASH --first-parent --tags +check_describe c-7-gHASH --tags --no-exact-match HEAD +check_describe e-3-gHASH --first-parent --tags --no-exact-match HEAD + +test_expect_success '--exact-match failure' ' + test_must_fail git describe --exact-match HEAD 2>err +' + test_expect_success 'describe --contains defaults to HEAD without commit-ish' ' echo "A^0" >expect && git checkout A && -- 2.41.0-376-gcba07a324d