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

Re: Add a "git-describe" command

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Dec 28, 2005, 02:05 UTC
Message-ID
<Pine.LNX.4.63.0512280300280.3194@wbgn013.biozentrum.uni-wuerzburg.de>
In-Reply-To
<7v7j9q3vdu.fsf@assigned-by-dhcp.cox.net>
Hi,
On Tue, 27 Dec 2005, Junio C Hamano wrote:
> One problem with git-describe is that getting tags is a concious
> user action, and you need to do "git fetch --tags" from time to
> time in order to see the v1.0.4-g6e9961d6 name.

This is probably the biggest problem. I trust you to set the correct version in the Makefile just before tagging it.

Also, Linus hinted at similarities between git-describe and git-name-rev:

--- [PATCH] Teach name-rev to understand the "--inverse" flag

If "--inverse" is passed to name-rev, instead of naming the given revs by the available refs, it does the opposite. The output is sorted by distance, i.e. how many hops are between the rev and the ref. If the ref is not an ancestor of the rev, the distance is inifinite, and the name is undefined.

You can combine "--inverse" with "--tags", in effect getting the list of tags ordered such that the tag describing the rev best comes first.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
	I guess this is what Linus has been hinting at when he said that
	git-name-rev could be adapted to achieve something similar to
	git-describe.
 name-rev.c |   85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 78 insertions(+), 7 deletions(-)
b1831f3f66f659445d2628dda73a1d79fc8c3b6f
diff --git a/name-rev.c b/name-rev.c
index 65333d4..4f7c04e 100644
--- a/name-rev.c
+++ b/name-rev.c
@@ -5,19 +5,21 @@
 #include "refs.h"
 
 static const char name_rev_usage[] =
-	"git-name-rev [--tags] ( --all | --stdin | commitish [commitish...] )\n";
+	"git-name-rev [--tags] ( --all | --stdin | \n"
+	"                       [--inverse] commitish [commitish...] )\n";
 
 typedef struct rev_name {
 	const char *tip_name;
 	int merge_traversals;
 	int generation;
+	int distance;
 } rev_name;
 
 static long cutoff = LONG_MAX;
 
 static void name_rev(struct commit *commit,
 		const char *tip_name, int merge_traversals, int generation,
-		int deref)
+		int distance, int deref)
 {
 	struct rev_name *name = (struct rev_name *)commit->object.util;
 	struct commit_list *parents;
@@ -50,6 +52,7 @@ copy_data:
 		name->tip_name = tip_name;
 		name->merge_traversals = merge_traversals;
 		name->generation = generation;
+		name->distance = distance;
 	} else
 		return;
 
@@ -66,10 +69,10 @@ copy_data:
 				sprintf(new_name, "%s^%d", tip_name, parent_number);
 
 			name_rev(parents->item, new_name,
-				merge_traversals + 1 , 0, 0);
+				merge_traversals + 1 , 0, distance + 1, 0);
 		} else {
 			name_rev(parents->item, tip_name, merge_traversals,
-				generation + 1, 0);
+				generation + 1, distance + 1, 0);
 		}
 	}
 }
@@ -98,7 +101,7 @@ static int name_ref(const char *path, co
 		while ((p = strchr(path, '/')))
 			path = p+1;
 
-		name_rev(commit, strdup(path), 0, 0, deref);
+		name_rev(commit, strdup(path), 0, 0, 0, deref);
 	}
 	return 0;
 }
@@ -118,12 +121,56 @@ static const char* get_rev_name(struct o
 
 	return buffer;
 }
-	
+
+typedef struct {
+	const char* name;
+	struct object* o;
+} named_commit_t;
+static named_commit_t* ref_list = NULL;
+static int ref_count = 0;
+
+static int inverse_build_ref_list(const char *path, const unsigned char *sha1)
+{
+	struct object *o = deref_tag(parse_object(sha1), path, 0);
+
+	if ((!tags_only || !strncmp(path, "refs/tags/", 10)) &&
+			o->type == commit_type) {
+		struct commit* commit = (struct commit*)o;
+
+		if (cutoff > commit->date)
+			cutoff = commit->date;
+
+		if ((ref_count % 256) == 0)
+			ref_list = xrealloc(ref_list,
+				sizeof(named_commit_t*) * (ref_count + 256));
+		ref_list[ref_count].name = strdup(path);
+		ref_list[ref_count].o = (struct object*)commit;
+		ref_count++;
+	}
+	return 0;
+}
+
+static int name_comp(const void* a, const void* b)
+{
+	const rev_name* c = ((const named_commit_t*)a)->o->util;
+	const rev_name* d = ((const named_commit_t*)b)->o->util;
+
+	if (!c)
+		return 1;
+	if (!d)
+		return -1;
+	if (c->distance > d->distance)
+		return 1;
+	if (c->distance < d->distance)
+		return -1;
+	return 0;
+}
+
 int main(int argc, char **argv)
 {
 	struct object_list *revs = NULL;
 	struct object_list **walker = &revs;
-	int as_is = 0, all = 0, transform_stdin = 0;
+	int as_is = 0, all = 0, inverse = 0, transform_stdin = 0;
 
 	setup_git_directory();
 
@@ -142,6 +189,9 @@ int main(int argc, char **argv)
 			} else if (!strcmp(*argv, "--tags")) {
 				tags_only = 1;
 				continue;
+			} else if (!strcmp(*argv, "--inverse")) {
+				inverse = 1;
+				continue;
 			} else if (!strcmp(*argv, "--all")) {
 				if (argc > 1)
 					die("Specify either a list, or --all, not both!");
@@ -181,6 +231,27 @@ int main(int argc, char **argv)
 		walker = &((*walker)->next);
 	}
 
+	if (inverse) {
+		int i;
+
+		if (transform_stdin || all || !revs)
+			usage(name_rev_usage);
+
+		for_each_ref(inverse_build_ref_list);
+		
+		tags_only = 0;
+		for (; revs; revs = revs->next)
+			name_ref(revs->name, revs->item->sha1);
+
+		qsort(ref_list, ref_count, sizeof(named_commit_t), name_comp);
+
+		for (i = 0; i < ref_count; i++)
+			printf("%s %s\n", ref_list[i].name,
+				get_rev_name(ref_list[i].o));
+
+		return 0;
+	}
+
 	for_each_ref(name_ref);
 
 	if (transform_stdin) {
-- 
1.0.GIT
Previous: Junio C HamanoNext: Junio C Hamano
Message 5 of 14 in “Add a "git-describe" command”
  1. Linus TorvaldsDec 24, 2005
  2. Linus TorvaldsDec 24, 2005
  3. M_Dec 25, 2005
  4. Junio C HamanoDec 28, 2005
  5. Johannes SchindelinDec 28, 2005
  6. 1/6 git-describe: really prefer tags only.Junio C Hamano, Dec 28, 2005
  7. 2/6 git-describe: use find_unique_abbrev()Junio C Hamano, Dec 28, 2005
  8. 3/6 git-describe: --tags and --abbrevJunio C Hamano, Dec 28, 2005
  9. 4/6 git-describe: still prefer annotated tag under --all and --tagsJunio C Hamano, Dec 28, 2005
  10. 5/6 git-describe: documentation.Junio C Hamano, Dec 28, 2005
  11. 6/6 Makefile: use git-describe to mark the git version.Junio C Hamano, Dec 28, 2005
  12. Junio C HamanoDec 25, 2005
  13. Linus TorvaldsDec 25, 2005
  14. Junio C HamanoDec 25, 2005

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.