Junio C Hamano <gitster@xxxxxxxxx> writes: > In order to resolve this correctly with the precedence rules, I > think you need to make refname_match() return the precedence number > (e.g. give 1 to "%.*s", 2 to "refs/%.*s", etc., using the index in > ref_rev_parse_rules[] array), and make this loop keep track of the > "best" match paying attention to the returned precedence. That is, something like this, perhaps. The resulting behaviour should match how "git rev-parse X" would give precedence to tag X over branch X by going this route. What do you think? refs.c | 8 +++----- remote.c | 13 ++++++++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/refs.c b/refs.c index 457fb78057..fd1a7f7478 100644 --- a/refs.c +++ b/refs.c @@ -495,11 +495,9 @@ int refname_match(const char *abbrev_name, const char *full_name) const char **p; const int abbrev_name_len = strlen(abbrev_name); - for (p = ref_rev_parse_rules; *p; p++) { - if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) { - return 1; - } - } + for (p = ref_rev_parse_rules; *p; p++) + if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) + return (p - ref_rev_parse_rules) + 1; return 0; } diff --git a/remote.c b/remote.c index 86e6098774..ed2f80e45c 100644 --- a/remote.c +++ b/remote.c @@ -1689,11 +1689,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 = -1; + for (ref = refs; ref; ref = ref->next) { - if (refname_match(name, ref->name)) - return ref; + int score = refname_match(name, ref->name); + + if ((score && (best_score < 0 || score < best_score))) { + best_match = ref; + best_score = score; + } } - return NULL; + return best_match; } struct ref *get_remote_ref(const struct ref *remote_refs, const char *name)