Re: can git-describe learn first-parent behavior?

Previous thread: Announce gitslave - manage a superproject with slave repositories by Seth Robertson on Monday, September 20, 2010 - 6:39 pm. (3 messages)

Next thread: CHEVRON/TEXACO by CHEVRON/TEXACO on Tuesday, September 21, 2010 - 12:37 am. (1 message)
From: Joshua Shrader
Date: Monday, September 20, 2010 - 10:58 pm

This seems like it would be a rather useful feature.  Suppose a
maintenance branch, maint/v1.0, is forked from master, and the branch
point is tagged something like "v1.0-stable".  The next commit on
master is tagged "v2.0-base", indicating that it is the first commit
of the new release.  Suppose two releases are made - a release for
public consumption of version 1.0, and a release for internal testing
from master (currently 2.0), and we want to embed the output of
git-describe into the builds.  If bugs were fixed on 1.0, and then 1.0
was merged into master, it seems perfectly possible to run
git-describe on master, but get the v1.0 tag in the output.

Is this just a poor workflow?  Am I using git-describe incorrectly?
Or, does a first-parent option to git-describe seem useful?

Thanks for the input.

Josh
--

From: Michael J Gruber
Date: Tuesday, September 21, 2010 - 2:34 am

If you know you want to describe HEAD based on v2 tags you can use

git describe --match v2\* --tags HEAD

"git describe" does not use the revision walk machinery so that it does
not have the --first-parent option. I'm not sure how useful that is, but
it's easy to implement.

Michael
--

From: Michael J Gruber
Date: Tuesday, September 21, 2010 - 2:35 am

so that git-describe searches first-parent history only when looking for
a named commit. This is useful for describing commits by tags on their
"main" (first-parent) branch.

git describe --contains --first-parent is forbidden because git name-rev
(which is called by that) favors first-parent transversal already,
although not strictly so.

Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
---
Notes:
    Is this considered useful? RFC because of lack of doc and test.
    I consider it easier than (and different from) --match in some cases.

 builtin/describe.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/builtin/describe.c b/builtin/describe.c
index 43caff2..6b2b599 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -22,6 +22,7 @@ static int tags;	/* Allow lightweight tags */
 static int longformat;
 static int abbrev = DEFAULT_ABBREV;
 static int max_candidates = 10;
+static int first_parent;
 static int found_names;
 static const char *pattern;
 static int always;
@@ -302,7 +303,7 @@ static void describe(const char *arg, int last_one)
 			if (!(p->object.flags & SEEN))
 				insert_by_date(p, &list);
 			p->object.flags |= c->object.flags;
-			parents = parents->next;
+			parents = first_parent ? NULL : parents->next;
 		}
 	}
 
@@ -380,6 +381,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 			   "only consider tags matching <pattern>"),
 		OPT_BOOLEAN(0, "always",     &always,
 			   "show abbreviated commit object as fallback"),
+		OPT_BOOLEAN(0, "first-parent",     &first_parent,
+			   "follow first parents only"),
 		{OPTION_STRING, 0, "dirty",  &dirty, "mark",
 			   "append <mark> on dirty working tree (default: \"-dirty\")",
 		 PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
@@ -397,6 +400,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 	if (longformat && abbrev == 0)
 		die("--long is incompatible with --abbrev=0");
 
+	if (contains && ...
From: Johannes Sixt
Date: Tuesday, September 21, 2010 - 3:03 am

Does it? Then explain this result:

git describe e5498e8a^2 e5498e8a^1~24 e5498e8a
v1.7.0.7
v1.7.1.1
v1.7.1.1-38-ge5498e8

v1.7.1.1 is 25 commits away, while v1.7.0.7 is a parent (the second).

AFAICS, git-describe does The Right Thing (--first-parent).

-- Hannes
--

From: Michael J Gruber
Date: Tuesday, September 21, 2010 - 4:49 am

I'm not saying it does the wrong thing. I'm saying it does not do
--first-parent but depth priority (where depth is a bit complicated),
which may or may not be the same as first-parent transversal/priority.
You picked one case where they coincide:

git describe --debug e5498e8a^2 e5498e8a^2~24 e5498e8a
v1.7.0.7
v1.7.0.5
searching to describe e5498e8a
 annotated         38 v1.7.1.1
 annotated        252 v1.7.1
 annotated        268 v1.7.1-rc2
 annotated        318 v1.7.1-rc1
 annotated        355 v1.7.1-rc0
 annotated        478 v1.7.0.7
 annotated        492 v1.7.0.6
 annotated        512 v1.7.0.5
 annotated        539 v1.7.0.4
 annotated        564 v1.7.0.3
traversed 1267 commits
more than 10 tags found; listed 10 most recent
gave up search at 97222d9634b5518cd3d328aa86b52746a16334a7
v1.7.1.1-38-ge5498e8

v1.7.1.1 clearly wins by depth priority.


In an example like Joshua's, it is obviously not the first parent which
wins by default:

* 771c6c7 (HEAD, master) more_development
*   88b63bd Merge branch 'maint'
|\
| * d99fb44 (tag: v1.1-stable, maint) v1.1-stable
* | c2f7480 development
* | 9480bca (tag: v2.0-base) v2.0-base
|/
* 31e78ef (tag: v1.0-stable) v1.0-stable

git describe --debug --tags  HEAD
searching to describe HEAD
 lightweight        4 v1.1-stable
 lightweight        4 v2.0-base
 lightweight        5 v1.0-stable
traversed 6 commits
v1.1-stable-4-g771c6c7

git describe --debug --tags --match v2\* HEAD
searching to describe HEAD
 lightweight        4 v2.0-base
traversed 6 commits
v2.0-base-4-g771c6c7

git describe --debug --tags --first-parent HEAD
searching to describe HEAD
 lightweight        3 v2.0-base
 lightweight        4 v1.0-stable
traversed 5 commits
v2.0-base-3-g771c6c7

The latter is with my RFC PATCH, of course.

Note that without the commit "development", v2.0-base wins even in the
first case, even though this does not change the first-parent relationships.

Cheers
Michael
--

From: Johannes Sixt
Date: Tuesday, September 21, 2010 - 5:00 am

If "depth priority" is not the shortest ancestry path (and it obviously is
not given the numbers above), what is it then, and why does it not work
with Joshua's example? Wouldn't it be better to make it Just Work instead
of adding a workaround that has to be enabled manually?

-- Hannes
--

From: Michael J Gruber
Date: Tuesday, September 21, 2010 - 5:10 am

Well, e5498e8a^2~24 == v1.7.0.5 and e5498e8a^1~24 == v1.7.1.1.
The copy&paste from your e-mail was not exactly helped by Thunderbirds
conversion of ^2, ^1 into exponents... In any case, the numbers below

I don't consider the existing behaviour wrong, though it may be a bit
tough to figure out. It may even be that the depth calculation has an
off-by-1 error which leads to this behaviour.

Consequently, I don't consider --first-parent a workaround. Note that
with --first-parent, tags on other branches are not even considered so
that you can be sure to get a first parent tag or none.

Do you really think that changing the algorithm would be accepted? In
any case, at most that would lead to prioritizing first parent tags
unconditionally but still resorting to other tags when there are no
first-parent tags.

Michael
--

From: Johannes Sixt
Date: Tuesday, September 21, 2010 - 5:34 am

I faintly recall that the current behavior was already made
--first-parent-like on purpose, exactly for cases like Joshua's and the
one I cited. Why does it work with mine, but not with Joshua's?

Notice that v1.7.0.7 is an immediate parent of e5498e8a, but still its
calculated "depth" is much higher than for v1.7.1.1, which is 25 commits
down in the history. Why? Why isn't it the same with Joshua's history? Is
it due to the commit dates? Or the tag dates?

-- Hannes
--

From: Michael J Gruber
Date: Tuesday, September 21, 2010 - 8:26 am

By experimentation (inserting additional tag-less commits, not changing
topology), I can make v2.0-base have the same, lower or higher depth
than v1.1-stable.

In fact, the (commit) date order is important here: For describing
<commit>, "describe" builds a 1 item list with commit, pops it, inserts
its parents in date order (!), looks at each item in that order, in each
step again inserting the parents in date order. So, it's really that the
branch with more newer commits wins (this is a lousy description, but
you get the idea).

Reading commit messages like 80dbae makes me think that this was
intended; and it is completely different from a first-parent approach.
So I think the default really is a good default as is, and first-parent
is useful and different in some cases.

Michael
--

From: Joshua Shrader
Date: Tuesday, September 21, 2010 - 12:57 pm

I think I need to apologize to the list.  I did not actually observe
what I had stated in my original post.  Given the description (and my
possibly naive understanding) of git-describe, I hypothesized that
what I originally stated was possible. If git-describe is in fact
implemented with a first-parent-like behavior, as some people believe
to be true, then I believe it is working correctly - I've seen nothing
to the contrary.  However, I do believe that the documentation is
unclear if this is the case.  My interpretation of "depth," which I
believe to be consistent with the graph-theoretical definition, does
imply that what I stated could happen.


On Tue, Sep 21, 2010 at 11:26 AM, Michael J Gruber
--

From: Michael J Gruber
Date: Tuesday, September 21, 2010 - 11:52 pm

Josh, no need to apologize. You simply tried to understand "git
describe". The mere fact that a Git long time contributor (J6t) and an
occasional contributor (I) are discussing "git describe"'s behaviour
tells you that it can't be that easy ;)

The man page says "most recent tag", and that is true, but with a
definition of "most recent" that you wouldn't expect. The description
there under "Search Strategy" is wrong, and has been at least since
80dbae03. I'll try to come up with a better explanation fit for the man
page, possibly after writing some more tests.

The intended behaviour is explained really well in Shawn's commit
message for 80dbae03. And if you look at the algorithm you see that the
order of the parents (as stored in a merge commit), in particular
first-parent relationship plays no role at all. The algo takes all
parents and inserts them in date order into a list to be looped over
afterwards.

The more I understand the algo the more I realize that --first-parent is
useful and completely different, and that I can optimize more in my patch.

Cheers
Michael
--

From: Joshua Shrader
Date: Wednesday, September 22, 2010 - 10:45 am

Thanks for the response.  Since my last message, I have been able to
get a tag on the v1.0 branch (although not the original v1.0-stable
tag) to appear in the git describe output when run on v1.1 head, and
thus I do think a --first-parent option would be useful.

On Wed, Sep 22, 2010 at 2:52 AM, Michael J Gruber
--

Previous thread: Announce gitslave - manage a superproject with slave repositories by Seth Robertson on Monday, September 20, 2010 - 6:39 pm. (3 messages)

Next thread: CHEVRON/TEXACO by CHEVRON/TEXACO on Tuesday, September 21, 2010 - 12:37 am. (1 message)