diff --git a/advice.c b/advice.c index 780f58da0f..22abde9bc4 100644 --- a/advice.c +++ b/advice.c @@ -12,6 +12,7 @@ int advice_commit_before_merge = 1; int advice_resolve_conflict = 1; int advice_implicit_identity = 1; int advice_detached_head = 1; +int advice_object_name_warning = 1; static struct { const char *name; @@ -29,6 +30,7 @@ static struct { { "resolveconflict", &advice_resolve_conflict }, { "implicitidentity", &advice_implicit_identity }, { "detachedhead", &advice_detached_head }, + { "object_name_warning", &advice_object_name_warning }, /* make this an alias for backward compatibility */ { "pushnonfastforward", &advice_push_update_rejected } diff --git a/advice.h b/advice.h index fad36df467..24d5420b7a 100644 --- a/advice.h +++ b/advice.h @@ -15,6 +15,7 @@ extern int advice_commit_before_merge; extern int advice_resolve_conflict; extern int advice_implicit_identity; extern int advice_detached_head; +extern int advice_object_name_warning; int git_default_advice_config(const char *var, const char *value); void advise(const char *advice, ...); diff --git a/sha1_name.c b/sha1_name.c index 95003c77ea..502d107a5e 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -435,12 +435,31 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l static int get_sha1_basic(const char *str, int len, unsigned char *sha1) { static const char *warn_msg = "refname '%.*s' is ambiguous."; + static const char *object_name_msg = N_( + "Git normally never creates a ref that ends with 40 hex characters\n" + "because it will be ignored when you just specify 40-hex. These refs\n" + "may be created by mistake. For example,\n" + "\n" + " git checkout -b $br $(git rev-parse ...)\n" + "\n" + "where \"$br\" is somehow empty and a 40-hex ref is created. Please\n" + "examine these refs and maybe delete them. Turn this message off by\n" + "running \"git config advice.object_name_warning false\""); + unsigned char tmp_sha1[20]; char *real_ref = NULL; int refs_found = 0; int at, reflog_len; - if (len == 40 && !get_sha1_hex(str, sha1)) + if (len == 40 && !get_sha1_hex(str, sha1)) { + refs_found = dwim_ref(str, len, tmp_sha1, &real_ref); + if (refs_found > 0 && warn_ambiguous_refs) { + warning(warn_msg, len, str); + if (advice_object_name_warning) + fprintf(stderr, "%s\n", _(object_name_msg)); + } + free(real_ref); return 0; + } /* basic@{time or number or -number} format to query ref-log */ reflog_len = at = 0; @@ -481,7 +500,9 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) if (!refs_found) return -1; - if (warn_ambiguous_refs && refs_found > 1) + if (warn_ambiguous_refs && + (refs_found > 1 || + !get_short_sha1(str, len, tmp_sha1, GET_SHA1_QUIETLY))) warning(warn_msg, len, str); if (reflog_len) { diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 6b3d797cea..db228086d3 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -261,4 +261,22 @@ test_expect_success 'rev-parse --disambiguate' ' test "$(sed -e "s/^\(.........\).*/\1/" actual | sort -u)" = 000000000 ' +test_expect_success 'ambiguous 40-hex ref' ' + TREE=$(git mktree err` = $REF && + grep "refname.*${REF}.*ambiguous" err +' + +test_expect_success 'ambiguous short sha1 ref' ' + TREE=$(git mktree err` = $VAL && + grep "refname.*${REF}.*ambiguous" err +' + test_done