diff options
author | Junio C Hamano <gitster@pobox.com> | 2016-05-31 14:08:26 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-05-31 14:08:26 -0700 |
commit | 9ee8f9409cab2a52e133c63bdd0acce24f99e73f (patch) | |
tree | ae5415974eeddde5030d4be51dcf531f354b1be1 | |
parent | b051c59a00dbe1b2316d10ac95c789de2ad35d18 (diff) | |
parent | 755042480429fbadbb1953416d2c04c035a78e4c (diff) | |
download | git-9ee8f9409cab2a52e133c63bdd0acce24f99e73f.tar.gz |
Merge branch 'js/name-rev-use-oldest-ref' into maint
"git describe --contains" often made a hard-to-justify choice of
tag to give name to a given commit, because it tried to come up
with a name with smallest number of hops from a tag, causing an old
commit whose close descendant that is recently tagged were not
described with respect to an old tag but with a newer tag. It did
not help that its computation of "hop" count was further tweaked to
penalize being on a side branch of a merge. The logic has been
updated to favor using the tag with the oldest tagger date, which
is a lot easier to explain to the end users: "We describe a commit
in terms of the (chronologically) oldest tag that contains the
commit."
* js/name-rev-use-oldest-ref:
name-rev: include taggerdate in considering the best name
-rw-r--r-- | builtin/name-rev.c | 19 | ||||
-rwxr-xr-x | t/t9903-bash-prompt.sh | 2 |
2 files changed, 14 insertions, 7 deletions
diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 092e03c3cc..57be35faf5 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -10,6 +10,7 @@ typedef struct rev_name { const char *tip_name; + unsigned long taggerdate; int generation; int distance; } rev_name; @@ -20,7 +21,8 @@ static long cutoff = LONG_MAX; #define MERGE_TRAVERSAL_WEIGHT 65535 static void name_rev(struct commit *commit, - const char *tip_name, int generation, int distance, + const char *tip_name, unsigned long taggerdate, + int generation, int distance, int deref) { struct rev_name *name = (struct rev_name *)commit->util; @@ -43,9 +45,12 @@ static void name_rev(struct commit *commit, name = xmalloc(sizeof(rev_name)); commit->util = name; goto copy_data; - } else if (name->distance > distance) { + } else if (name->taggerdate > taggerdate || + (name->taggerdate == taggerdate && + name->distance > distance)) { copy_data: name->tip_name = tip_name; + name->taggerdate = taggerdate; name->generation = generation; name->distance = distance; } else @@ -66,11 +71,11 @@ copy_data: new_name = xstrfmt("%.*s^%d", (int)len, tip_name, parent_number); - name_rev(parents->item, new_name, 0, + name_rev(parents->item, new_name, taggerdate, 0, distance + MERGE_TRAVERSAL_WEIGHT, 0); } else { - name_rev(parents->item, tip_name, generation + 1, - distance + 1, 0); + name_rev(parents->item, tip_name, taggerdate, + generation + 1, distance + 1, 0); } } } @@ -140,6 +145,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo struct name_ref_data *data = cb_data; int can_abbreviate_output = data->tags_only && data->name_only; int deref = 0; + unsigned long taggerdate = ULONG_MAX; if (data->tags_only && !starts_with(path, "refs/tags/")) return 0; @@ -164,12 +170,13 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo break; /* broken repository */ o = parse_object(t->tagged->oid.hash); deref = 1; + taggerdate = t->date; } if (o && o->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)o; path = name_ref_abbrev(path, can_abbreviate_output); - name_rev(commit, xstrdup(path), 0, 0, deref); + name_rev(commit, xstrdup(path), taggerdate, 0, 0, deref); } return 0; } diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh index ffbfa0efb8..0db4469c89 100755 --- a/t/t9903-bash-prompt.sh +++ b/t/t9903-bash-prompt.sh @@ -107,7 +107,7 @@ test_expect_success 'prompt - describe detached head - contains' ' ' test_expect_success 'prompt - describe detached head - branch' ' - printf " ((b1~1))" >expected && + printf " ((tags/t2~1))" >expected && git checkout b1^ && test_when_finished "git checkout master" && ( |