Skip to content

Commit 798c35f

Browse files
pcloudsgitster
authored andcommitted
get_sha1: warn about full or short object names that look like refs
When we get 40 hex digits, we immediately assume it's an SHA-1. This is the right thing to do because we have no way else to specify an object. If there is a ref with the same object name, it will be ignored. Warn the user about this case because the ref with full object name is likely a mistake, for example git checkout -b $empty_var $(git rev-parse something) advice.object_name_warning is not documented because frankly people should not be aware about it until they encounter this situation. While at there, warn about ambiguation with abbreviated SHA-1 too. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 239222f commit 798c35f

File tree

4 files changed

+44
-2
lines changed

4 files changed

+44
-2
lines changed

advice.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ int advice_commit_before_merge = 1;
1212
int advice_resolve_conflict = 1;
1313
int advice_implicit_identity = 1;
1414
int advice_detached_head = 1;
15+
int advice_object_name_warning = 1;
1516

1617
static struct {
1718
const char *name;
@@ -29,6 +30,7 @@ static struct {
2930
{ "resolveconflict", &advice_resolve_conflict },
3031
{ "implicitidentity", &advice_implicit_identity },
3132
{ "detachedhead", &advice_detached_head },
33+
{ "object_name_warning", &advice_object_name_warning },
3234

3335
/* make this an alias for backward compatibility */
3436
{ "pushnonfastforward", &advice_push_update_rejected }

advice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ extern int advice_commit_before_merge;
1515
extern int advice_resolve_conflict;
1616
extern int advice_implicit_identity;
1717
extern int advice_detached_head;
18+
extern int advice_object_name_warning;
1819

1920
int git_default_advice_config(const char *var, const char *value);
2021
void advise(const char *advice, ...);

sha1_name.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,12 +435,31 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l
435435
static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
436436
{
437437
static const char *warn_msg = "refname '%.*s' is ambiguous.";
438+
static const char *object_name_msg = N_(
439+
"Git normally never creates a ref that ends with 40 hex characters\n"
440+
"because it will be ignored when you just specify 40-hex. These refs\n"
441+
"may be created by mistake. For example,\n"
442+
"\n"
443+
" git checkout -b $br $(git rev-parse ...)\n"
444+
"\n"
445+
"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
446+
"examine these refs and maybe delete them. Turn this message off by\n"
447+
"running \"git config advice.object_name_warning false\"");
448+
unsigned char tmp_sha1[20];
438449
char *real_ref = NULL;
439450
int refs_found = 0;
440451
int at, reflog_len;
441452

442-
if (len == 40 && !get_sha1_hex(str, sha1))
453+
if (len == 40 && !get_sha1_hex(str, sha1)) {
454+
refs_found = dwim_ref(str, len, tmp_sha1, &real_ref);
455+
if (refs_found > 0 && warn_ambiguous_refs) {
456+
warning(warn_msg, len, str);
457+
if (advice_object_name_warning)
458+
fprintf(stderr, "%s\n", _(object_name_msg));
459+
}
460+
free(real_ref);
443461
return 0;
462+
}
444463

445464
/* basic@{time or number or -number} format to query ref-log */
446465
reflog_len = at = 0;
@@ -481,7 +500,9 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
481500
if (!refs_found)
482501
return -1;
483502

484-
if (warn_ambiguous_refs && refs_found > 1)
503+
if (warn_ambiguous_refs &&
504+
(refs_found > 1 ||
505+
!get_short_sha1(str, len, tmp_sha1, GET_SHA1_QUIETLY)))
485506
warning(warn_msg, len, str);
486507

487508
if (reflog_len) {

t/t1512-rev-parse-disambiguation.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,4 +261,22 @@ test_expect_success 'rev-parse --disambiguate' '
261261
test "$(sed -e "s/^\(.........\).*/\1/" actual | sort -u)" = 000000000
262262
'
263263

264+
test_expect_success 'ambiguous 40-hex ref' '
265+
TREE=$(git mktree </dev/null) &&
266+
REF=`git rev-parse HEAD` &&
267+
VAL=$(git commit-tree $TREE </dev/null) &&
268+
git update-ref refs/heads/$REF $VAL &&
269+
test `git rev-parse $REF 2>err` = $REF &&
270+
grep "refname.*${REF}.*ambiguous" err
271+
'
272+
273+
test_expect_success 'ambiguous short sha1 ref' '
274+
TREE=$(git mktree </dev/null) &&
275+
REF=`git rev-parse --short HEAD` &&
276+
VAL=$(git commit-tree $TREE </dev/null) &&
277+
git update-ref refs/heads/$REF $VAL &&
278+
test `git rev-parse $REF 2>err` = $VAL &&
279+
grep "refname.*${REF}.*ambiguous" err
280+
'
281+
264282
test_done

0 commit comments

Comments
 (0)