threads / patch / 6558

patch, 4 partsIf abbrev is set to zero in git-describe, don't add the unique suffix

Subject: [PATCH 2/4] If abbrev is set to zero in git-describe, don't add the unique suffix

## tl;dr

6 messages between Jan 27, 2007 and Jan 28, 2007. Diffs are folded; open one to read it.

replies: 5people: 3as markdown or json

Shawn O. Pearce· Jan 27, 2007, 06:53 UTC · lore
From: Andy Parkins <andyparkins@gmail.com>
When on a non-tag commit, git-describe normally outputs descriptions of
the form
  v1.0.0-g1234567890
Some scripts (for example the update hook script) might just want to
know the name of the nearest tag, so they then have to do
 x=$(git-describe HEAD | sed 's/-g*//')
This is costly, but more importantly is fragile as it is relying on the
output format of git-describe, which we would then have to maintain
forever.

This patch adds support for setting the --abbrev option to zero. In that case git-describe does as it always has, but outputs only the nearest found tag instead of a completely unique name. This means that scripts would not have to parse the output format and won't need changing if the git-describe suffix is ever changed.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 This is a resend of Andy's original patch.  I added documentation
 updates and slighlty modified the code so it conformed to our
 conventions.  Reason is, my next patch alters the same lines...
 Documentation/git-describe.txt |    7 ++++++-
 builtin-describe.c             |    9 ++++++---
 2 files changed, 12 insertions(+), 4 deletions(-)
Show changes to 2 files +12 −4

Documentation/git-describe.txt, builtin-describe.c

diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index b87783c..a615996 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -33,7 +33,9 @@ OPTIONS
 
 --abbrev=<n>::
 	Instead of using the default 8 hexadecimal digits as the
-	abbreviated object name, use <n> digits.
+	abbreviated object name, use <n> digits.  If set to 0
+	then abbreviated object name will not be displayed on
+	a non-exact match.
 
 --candidates=<n>::
 	Instead of considering only the 10 most recent tags as
@@ -70,6 +72,9 @@ the output shows the reference path as well:
 	[torvalds@g5 git]$ git describe --all --abbrev=4 v1.0.5^2
 	tags/v1.0.0-g975b
 
+	[torvalds@g5 git]$ git describe --all --abbrev=0 v1.0.5^2
+	tags/v1.0.0
+
 	[torvalds@g5 git]$ git describe --all HEAD^
 	heads/lt/describe-g975b
 
diff --git a/builtin-describe.c b/builtin-describe.c
index f8afb9c..70578dc 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -188,8 +188,11 @@ static void describe(const char *arg, int last_one)
 				sha1_to_hex(gave_up_on->object.sha1));
 		}
 	}
-	printf("%s-g%s\n", all_matches[0].name->path,
-		   find_unique_abbrev(cmit->object.sha1, abbrev));
+	if (!abbrev)
+		printf("%s\n", all_matches[0].name->path);
+	else
+		printf("%s-g%s\n", all_matches[0].name->path,
+			find_unique_abbrev(cmit->object.sha1, abbrev));
 
 	if (!last_one)
 		clear_commit_marks(cmit, -1);
@@ -212,7 +215,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 			tags = 1;
 		else if (!strncmp(arg, "--abbrev=", 9)) {
 			abbrev = strtoul(arg + 9, NULL, 10);
-			if (abbrev < MINIMUM_ABBREV || 40 < abbrev)
+			if (abbrev && (abbrev < MINIMUM_ABBREV || 40 < abbrev))
 				abbrev = DEFAULT_ABBREV;
 		}
 		else if (!strncmp(arg, "--candidates=", 13)) {
-- 
1.5.0.rc2.g8a816
Shawn O. Pearce· Jan 27, 2007, 06:54 UTC · lore

[PATCH 3/4] Teach git-describe to display distances from tags.

Junio C Hamano <junkio@cox.net>:
Show 14 quoted lines
> However, I suspect that we could do better with Shawn's new
> fangled describe implementation that actually counts the
> distance between what is described and the tag.  We could add
> "number of commits since the tag" somewhere, to describe:
>
>   v2.6.20-rc5-256-g419dd83
>   v2.6.20-rc5-217-gde14569
>
> to say that the first one has 256 commits accumulated since the
> given tag "v2.6.20-rc5" and the second one has only 217
> commits, to get the sense of how busy the development activity
> is.
>
> Is it useful?  That is something I am not sure.

Yes, its very useful. If you get two different describes at different times from a non-rewinding branch and they both come up with the same tag name, you can tell which is the 'newer' one by distance. This is rather common in practice, so its incredibly useful.

Credit for this idea also goes to Jakub Narebski for suggesting:
    v2.6.20-rc5+256-g419dd83
    v2.6.20-rc5+217-gde14569

The + format is much easier to read and understand than the - format original proposed by Junio.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 Documentation/git-describe.txt |   23 ++++++++++++++---------
 builtin-describe.c             |    3 ++-
 2 files changed, 16 insertions(+), 10 deletions(-)
Show changes to 2 files +16 −10

Documentation/git-describe.txt, builtin-describe.c

diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index a615996..b3e9276 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -14,8 +14,8 @@ DESCRIPTION
 -----------
 The command finds the most recent tag that is reachable from a
 commit, and if the commit itself is pointed at by the tag, shows
-the tag.  Otherwise, it suffixes the tag name with abbreviated
-object name of the commit.
+the tag.  Otherwise, it suffixes the tag name with the number of
+additional commits and the abbreviated object name of the commit.
 
 
 OPTIONS
@@ -54,12 +54,17 @@ EXAMPLES
 With something like git.git current tree, I get:
 
 	[torvalds@g5 git]$ git-describe parent
-	v1.0.4-g2414721b
+	v1.0.4+14-g2414721
 
-i.e. the current head of my "parent" branch is based on v1.0.4,
-but since it has a few commits on top of that, it has added the
-git hash of the thing to the end: "-g" + 8-char shorthand for
-the commit `2414721b194453f058079d897d13c4e377f92dc6`.
+i.e. the current head of my "parent" branch is based on v1.0.4.
+But since my parent branch has a few commits on top of that,
+describe has added the number of additional commits ("+14") and
+the hash of the tip commit ("-g2414721") to the end.
+
+The number of additional commits is an estimate of the number
+of commits which would be displayed by "git log v1.0.4..parent".
+The hash suffix is "-g" + 8-char abbreviation for the tip commit
+of parent (which was `2414721b194453f058079d897d13c4e377f92dc6`).
 
 Doing a "git-describe" on a tag-name will just show the tag name:
 
@@ -70,13 +75,13 @@ With --all, the command can use branch heads as references, so
 the output shows the reference path as well:
 
 	[torvalds@g5 git]$ git describe --all --abbrev=4 v1.0.5^2
-	tags/v1.0.0-g975b
+	tags/v1.0.0+21-g975b
 
 	[torvalds@g5 git]$ git describe --all --abbrev=0 v1.0.5^2
 	tags/v1.0.0
 
 	[torvalds@g5 git]$ git describe --all HEAD^
-	heads/lt/describe-g975b
+	heads/lt/describe+5-g975b
 
 SEARCH STRATEGY
 ---------------
diff --git a/builtin-describe.c b/builtin-describe.c
index 70578dc..6e59e75 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -191,7 +191,8 @@ static void describe(const char *arg, int last_one)
 	if (!abbrev)
 		printf("%s\n", all_matches[0].name->path);
 	else
-		printf("%s-g%s\n", all_matches[0].name->path,
+		printf("%s+%d-g%s\n", all_matches[0].name->path,
+			all_matches[0].depth,
 			find_unique_abbrev(cmit->object.sha1, abbrev));
 
 	if (!last_one)
-- 
1.5.0.rc2.g8a816
Junio C Hamano· Jan 27, 2007, 08:47 UTC · re: Shawn O. Pearce · lore

Re: [PATCH 3/4] Teach git-describe to display distances from tags.

"Shawn O. Pearce" <spearce@spearce.org> writes:
Show 14 quoted lines
> Junio C Hamano <junkio@cox.net>:
>> However, I suspect that we could do better with Shawn's new
>> fangled describe implementation that actually counts the
>> distance between what is described and the tag.  We could add
>> "number of commits since the tag" somewhere, to describe:
>>
>>   v2.6.20-rc5-256-g419dd83
>>   v2.6.20-rc5-217-gde14569
> ...
>     v2.6.20-rc5+256-g419dd83
>     v2.6.20-rc5+217-gde14569
>
> The + format is much easier to read and understand than the - format
> original proposed by Junio.

I tend to disagree (I do not claim + is _less_ easier to read, though).

They are of comparable readability, and I think plus breaks GIT-VERSION-GEN (the primary reason it replaces '-' to '.' is to work around RPM limitation IIRC, and I do not know what '+' does to RPM offhand).

But I do not have a strong feeling either way.
Johannes Schindelin· Jan 27, 2007, 12:50 UTC · re: Junio C Hamano · lore

Re: [PATCH 3/4] Teach git-describe to display distances from tags.

Hi,
On Sat, 27 Jan 2007, Junio C Hamano wrote:
Show 11 quoted lines
> "Shawn O. Pearce" <spearce@spearce.org> writes:
> 
> > The + format is much easier to read and understand than the - format 
> > original proposed by Junio.
> 
> I tend to disagree (I do not claim + is _less_ easier to read, though).
> 
> They are of comparable readability, and I think plus breaks 
> GIT-VERSION-GEN (the primary reason it replaces '-' to '.' is to work 
> around RPM limitation IIRC, and I do not know what '+' does to RPM 
> offhand).

Note that scripts using git-describe to name archives break also on challenged file / operating systems. IIRC on DOS/FAT32 '+' has problems with it.

> But I do not have a strong feeling either way.
Neither have I.

Ciao, Dscho

Shawn O. Pearce· Jan 28, 2007, 07:24 UTC · re: Johannes Schindelin · lore

Re: [PATCH 3/4] Teach git-describe to display distances from tags.

Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 20 quoted lines
> On Sat, 27 Jan 2007, Junio C Hamano wrote:
> > "Shawn O. Pearce" <spearce@spearce.org> writes:
> > 
> > > The + format is much easier to read and understand than the - format 
> > > original proposed by Junio.
> > 
> > I tend to disagree (I do not claim + is _less_ easier to read, though).
> > 
> > They are of comparable readability, and I think plus breaks 
> > GIT-VERSION-GEN (the primary reason it replaces '-' to '.' is to work 
> > around RPM limitation IIRC, and I do not know what '+' does to RPM 
> > offhand).
> 
> Note that scripts using git-describe to name archives break also on 
> challenged file / operating systems. IIRC on DOS/FAT32 '+' has problems 
> with it.
> 
> > But I do not have a strong feeling either way.
> 
> Neither have I.

Me neither, actually. The + just felt more right, as its literally "that tag, plus n commits".

But if + is going to cause pain on operating systems that somehow decided disallowing bytes other than NUL was OK and the right thing to do, then maybe - is the safer choice here.

-- 
Shawn.
Shawn O. Pearce· Jan 27, 2007, 06:54 UTC · lore

[PATCH 4/4] Compute accurate distances in git-describe before output.

My prior change to git-describe attempts to print the distance between the input commit and the best matching tag, but this distance was usually only an estimate as we always aborted revision walking as soon as we overflowed the configured limit on the number of possible tags (as set by --candidates).

Displaying an estimated distance is not very useful and can just be downright confusing. Most users (heck, most Git developers) don't immediately understand why this distance differs from the output of common tools such as `git rev-list | wc -l`. Even worse, the estimated distance could change in the future (including decreasing despite no rebase occuring) if we find more possible tags earlier on during traversal. (This could happen if more tags are merged into the branch between queries.) These factors basically make an estimated distance useless.

Fortunately we are usually most of the way through an accurate distance computation by the time we abort (due to reaching the current --candidates limit). This means we can simply finish counting out the revisions still in our commit queue to present the accurate distance at the end. The number of commits remaining in the commit queue is probably less than the number of commits already traversed, so finishing out the count is not likely to take very long. This final distance will then always match the output of `git rev-list | wc -l`.

We can easily reduce the total number of commits that need to be walked at the end by stopping as soon as all of the commits in the commit queue are flagged as being merged into the already selected best possible tag. If that's true then there are no remaining unseen commits which can contribute to our best possible tag's depth counter, so further traversal is useless.

Basic testing on my Mac OS X system shows there is no noticable performance difference between this accurate distance counting version of git-describe and the prior version of git-describe, at least when run on git.git.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 Documentation/git-describe.txt |    2 +-
 builtin-describe.c             |   42 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 2 deletions(-)
Show changes to 2 files +42 −2

Documentation/git-describe.txt, builtin-describe.c

diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index b3e9276..160779a 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -61,7 +61,7 @@ But since my parent branch has a few commits on top of that,
 describe has added the number of additional commits ("+14") and
 the hash of the tip commit ("-g2414721") to the end.
 
-The number of additional commits is an estimate of the number
+The number of additional commits shown after the tag is the number
 of commits which would be displayed by "git log v1.0.4..parent".
 The hash suffix is "-g" + 8-char abbreviation for the tip commit
 of parent (which was `2414721b194453f058079d897d13c4e377f92dc6`).
diff --git a/builtin-describe.c b/builtin-describe.c
index 6e59e75..2ad3c16 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -91,6 +91,39 @@ static int compare_pt(const void *a_, const void *b_)
 	return 0;
 }
 
+static unsigned long finish_depth_computation(
+	struct commit_list **list,
+	struct possible_tag *best)
+{
+	unsigned long seen_commits = 0;
+	while (*list) {
+		struct commit *c = pop_commit(list);
+		struct commit_list *parents = c->parents;
+		seen_commits++;
+		if (c->object.flags & best->flag_within) {
+			struct commit_list *a = *list;
+			while (a) {
+				struct commit *i = a->item;
+				if (!(i->object.flags & best->flag_within))
+					break;
+				a = a->next;
+			}
+			if (!a)
+				break;
+		} else
+			best->depth++;
+		while (parents) {
+			struct commit *p = parents->item;
+			parse_commit(p);
+			if (!(p->object.flags & SEEN))
+				insert_by_date(p, list);
+			p->object.flags |= c->object.flags;
+			parents = parents->next;
+		}
+	}
+	return seen_commits;
+}
+
 static void describe(const char *arg, int last_one)
 {
 	unsigned char sha1[20];
@@ -166,12 +199,19 @@ static void describe(const char *arg, int last_one)
 			parents = parents->next;
 		}
 	}
-	free_commit_list(list);
 
 	if (!match_cnt)
 		die("cannot describe '%s'", sha1_to_hex(cmit->object.sha1));
 
 	qsort(all_matches, match_cnt, sizeof(all_matches[0]), compare_pt);
+
+	if (gave_up_on) {
+		insert_by_date(gave_up_on, &list);
+		seen_commits--;
+	}
+	seen_commits += finish_depth_computation(&list, &all_matches[0]);
+	free_commit_list(list);
+
 	if (debug) {
 		for (cur_match = 0; cur_match < match_cnt; cur_match++) {
 			struct possible_tag *t = &all_matches[cur_match];
-- 
1.5.0.rc2.g8a816

← back to recent threads