git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 5/5] describe: Break annotated tag ties by tagger date

From
Shawn O. Pearce <spearce@spearce.org>
Date
Apr 12, 2010, 23:25 UTC
Message-ID
<1271114729-18166-5-git-send-email-spearce@spearce.org>
In-Reply-To
<20100411024008.GC23075@spearce.org>

If more than one annotated tag points at the same commit, use the tag whose tagger field has a more recent date stamp. This resolves non-deterministic cases where the maintainer has done:

  $ git tag -a -m "2.1-rc1" v2.1-rc1  deadbeef
  $ git tag -a -m "2.1"     v2.1      deadbeef

If the tag is an older-style annotated tag with no tagger date, we assume a date stamp of 1 second after the UNIX epoch. This will cause us to prefer an annotated tag that has a valid date, or to simply avoid scanning the tag object again if a 3rd tag was found for the same commit.

We could also try to consider the tag object chain, favoring a tag that "includes" another one:

  $ git tag -a -m "2.1-rc0" v2.1-rc1  deadbeef
  $ git tag -a -m "2.1"     v2.1      v2.1-rc1

However traversing the tag's object chain looking for inclusion is much more complicated. Its already very likely that even in these cases the v2.1 tag will have a more recent tagger date than v2.1-rc1, so with this change describe should still resolve this by selecting the more recent v2.1.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 builtin/describe.c  |   49 +++++++++++++++++++++++++++++++++++++++++++++----
 t/t6120-describe.sh |    8 +++++---
 2 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/builtin/describe.c b/builtin/describe.c
index 71be2a9..43caff2 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -35,7 +35,8 @@ static const char *diff_index_args[] = {
 
 struct commit_name {
 	struct tag *tag;
-	int prio; /* annotated tag = 2, tag = 1, head = 0 */
+	unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */
+	unsigned name_checked:1;
 	unsigned char sha1[20];
 	char path[FLEX_ARRAY]; /* more */
 };
@@ -43,18 +44,53 @@ static const char *prio_names[] = {
 	"head", "lightweight", "annotated",
 };
 
+static int replace_name(struct commit_name *e,
+			       int prio,
+			       const unsigned char *sha1,
+			       struct tag **tag)
+{
+	if (!e || e->prio < prio)
+		return 1;
+
+	if (e->prio == 2 && prio == 2) {
+		/* Multiple annotated tags point to the same commit.
+		 * Select one to keep based upon their tagger date.
+		 */
+		struct tag *t;
+
+		if (!e->tag) {
+			t = lookup_tag(e->sha1);
+			if (!t || parse_tag(t))
+				return 1;
+			e->tag = t;
+		}
+
+		t = lookup_tag(sha1);
+		if (!t || parse_tag(t))
+			return 0;
+		*tag = t;
+
+		if (e->tag->date < t->date)
+			return 1;
+	}
+
+	return 0;
+}
+
 static void add_to_known_names(const char *path,
 			       struct commit *commit,
 			       int prio,
 			       const unsigned char *sha1)
 {
 	struct commit_name *e = commit->util;
-	if (!e || e->prio < prio) {
+	struct tag *tag = NULL;
+	if (replace_name(e, prio, sha1, &tag)) {
 		size_t len = strlen(path)+1;
 		free(e);
 		e = xmalloc(sizeof(struct commit_name) + len);
-		e->tag = NULL;
+		e->tag = tag;
 		e->prio = prio;
+		e->name_checked = 0;
 		hashcpy(e->sha1, sha1);
 		memcpy(e->path, path, len);
 		commit->util = e;
@@ -165,10 +201,15 @@ static void display_name(struct commit_name *n)
 {
 	if (n->prio == 2 && !n->tag) {
 		n->tag = lookup_tag(n->sha1);
-		if (!n->tag || parse_tag(n->tag) || !n->tag->tag)
+		if (!n->tag || parse_tag(n->tag))
 			die("annotated tag %s not available", n->path);
+	}
+	if (n->tag && !n->name_checked) {
+		if (!n->tag->tag)
+			die("annotated tag %s has no embedded name", n->path);
 		if (strcmp(n->tag->tag, all ? n->path + 5 : n->path))
 			warning("tag '%s' is really '%s' here", n->tag->tag, n->path);
+		n->name_checked = 1;
 	}
 
 	if (n->tag)
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 065dead..876d1ab 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -8,7 +8,7 @@ test_description='test describe
  o----o----o----o----o----.    /
        \        A    c        /
         .------------o---o---o
-                     D   e
+                   D,R   e
 '
 . ./test-lib.sh
 
@@ -68,6 +68,8 @@ test_expect_success setup '
 	echo D >another && git add another && git commit -m D &&
 	test_tick &&
 	git tag -a -m D D &&
+	test_tick &&
+	git tag -a -m R R &&
 
 	test_tick &&
 	echo DD >another && git commit -a -m another &&
@@ -89,10 +91,10 @@ test_expect_success setup '
 
 check_describe A-* HEAD
 check_describe A-* HEAD^
-check_describe D-* HEAD^^
+check_describe R-* HEAD^^
 check_describe A-* HEAD^^2
 check_describe B HEAD^^2^
-check_describe D-* HEAD^^^
+check_describe R-* HEAD^^^
 
 check_describe c-* --tags HEAD
 check_describe c-* --tags HEAD^
-- 
1.7.1.rc1.246.g978a8
Previous: Shawn O. PearceNext: Andreas Ericsson
Message 12 of 17 in “git describe bug?”
  1. Dustin SallingsApr 2, 2010
  2. Shawn O. PearceApr 2, 2010
  3. Andreas EricssonApr 6, 2010
  4. Shawn O. PearceApr 11, 2010
  5. describe: Break annotated tag ties by tagger dateShawn O. Pearce, Apr 11, 2010
  6. Junio C HamanoApr 11, 2010
  7. Shawn O. PearceApr 11, 2010
  8. 1/5 tag.c: Correct indentationShawn O. Pearce, Apr 12, 2010
  9. 2/5 tag.h: Remove unused signature fieldShawn O. Pearce, Apr 12, 2010
  10. 3/5 tag.c: Refactor parse_tag_buffer to be saner to programShawn O. Pearce, Apr 12, 2010
  11. 4/5 tag.c: Parse tagger date (if present)Shawn O. Pearce, Apr 12, 2010
  12. 5/5 describe: Break annotated tag ties by tagger dateShawn O. Pearce, Apr 12, 2010
  13. Andreas EricssonApr 13, 2010
  14. Thomas RastApr 13, 2010
  15. Shawn O. PearceApr 13, 2010
  16. Junio C HamanoApr 13, 2010
  17. Shawn O. PearceApr 13, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.