Hi, Junio C Hamano wrote: > When matching a non-wildcard LHS of a refspec against a list of > refs, find_ref_by_name_abbrev() returns the first ref that matches > using any DWIM rules used by refname_match() in refs.c, even if a > better match occurs later in the list of refs. Nicely explained. [...] > --- a/refs.c > +++ b/refs.c > @@ -487,16 +487,22 @@ static const char *ref_rev_parse_rules[] = { > NULL > }; > > +/* > + * Is it possible that the caller meant full_name with abbrev_name? > + * If so return a non-zero value to signal "yes"; the magnitude of > + * the returned value gives the precedence used for disambiguation. > + * > + * If abbrev_name cannot mean full_name, return 0. > + */ > int refname_match(const char *abbrev_name, const char *full_name) > { > const char **p; > const int abbrev_name_len = strlen(abbrev_name); > + const int num_rules = ARRAY_SIZE(ref_rev_parse_rules) - 1; This is assuming ref_rev_parse_rules consists exactly of its items followed by a NULL terminator, which is potentially a bit subtle. I wonder if we should put static const char *ref_rev_parse_rules[] = { "%.*s", "refs/%.*s", "refs/tags/%.*s", "refs/heads/%.*s", "refs/remotes/%.*s", "refs/remotes/%.*s/HEAD", NULL }; #define NUM_REV_PARSE_RULES (ARRAY_SIZE(ref_rev_parse_rules) - 1) and then use something like const int num_rules = NUM_REV_PARSE_RULES; so that this dependency is more obvious if the ref_rev_parse_rules convention changes later. Alternatively, what would you think of using the simpler return convention return p - ref_rev_parse_rules + 1; ? Or even return p - ref_rev_parse_rules; and -1 for "no match"? [...] > --- a/remote.c > +++ b/remote.c > @@ -1880,11 +1880,18 @@ static struct ref *get_expanded_map(const struct ref *remote_refs, > static const struct ref *find_ref_by_name_abbrev(const struct ref *refs, const char *name) > { > const struct ref *ref; > + const struct ref *best_match = NULL; > + int best_score = 0; > + > for (ref = refs; ref; ref = ref->next) { > - if (refname_match(name, ref->name)) > - return ref; > + int score = refname_match(name, ref->name); > + > + if (best_score < score) { > + best_match = ref; > + best_score = score; > + } > } > - return NULL; > + return best_match; Sensible and simple. If we wanted to make items earlier in the list return a lower value from refname_match, then we'd need a !best_score test here, which might be what motivates that return value convention. [...] > --- a/t/t5510-fetch.sh > +++ b/t/t5510-fetch.sh > @@ -535,6 +535,41 @@ test_expect_success "should be able to fetch with duplicate refspecs" ' > ) > ' > > +test_expect_success 'LHS of refspec follows ref disambiguation rules' ' Clearly illustrates the bug this fixes, in a way that makes it obvious that a user would prefer the new behavior. Good. With or without the tweak of introducing NUM_REV_PARSE_RULES mentioned above, Reviewed-by: Jonathan Nieder <jrnieder@xxxxxxxxx> Thanks.