diff mbox series

[1/2] revision: Denote root commits with '#'

Message ID 20210117110337.429994-2-kmarek@pdinc.us (mailing list archive)
State New
Headers show
Series Option to modify revision mark for root commits | expand

Commit Message

Kyle Marek Jan. 17, 2021, 11:03 a.m. UTC
This aids in identifying where an unrelated branch history starts when
using `git log --graph --oneline --all`

Signed-off-by: Kyle Marek <kmarek@pdinc.us>
---
 revision.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

Comments

Junio C Hamano Jan. 17, 2021, 9:10 p.m. UTC | #1
Kyle Marek <kmarek@pdinc.us> writes:

> This aids in identifying where an unrelated branch history starts when
> using `git log --graph --oneline --all`
>
> Signed-off-by: Kyle Marek <kmarek@pdinc.us>
> ---
>  revision.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)

No tests?

> diff --git a/revision.c b/revision.c
> index 9dff845bed..8556923de8 100644
> --- a/revision.c
> +++ b/revision.c
> @@ -4191,9 +4191,11 @@ const char *get_revision_mark(const struct rev_info *revs, const struct commit *
>  			return "<";
>  		else
>  			return ">";
> -	} else if (revs->graph)
> +	} else if (revs->graph) {
> +		if (!commit->parents)
> +			return "#";
>  		return "*";
> -	else if (revs->cherry_mark)
> +	} else if (revs->cherry_mark)
>  		return "+";
>  	return "";
>  }

Here is what I tried to come up with, but somehow the "#" marker is
not showing for me.

The "counted plus --left-right" tests stress why a single "#" is not
good enough.  I think the patch also needs to replace "<" and ">"
for root commits that are left and right---in the tests, I used "L"
to denote "root that is on the left side" (and "R" for the right
side) instead of single "#", so that we do not to lose information.

By the way, as I already said in the original thread, I do not think
the '#' marking is a good idea; I'd rather see the root commit shown
by shifting columns.

Anyway, here is to test [1/2].

 t/t6020-rev-list-boundary.sh | 132 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 132 insertions(+)

diff --git i/t/t6020-rev-list-boundary.sh w/t/t6020-rev-list-boundary.sh
new file mode 100755
index 0000000000..f25e041951
--- /dev/null
+++ w/t/t6020-rev-list-boundary.sh
@@ -0,0 +1,132 @@
+#!/bin/sh
+
+test_description='rev-list/log boundary and root'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	test_commit A &&
+	test_commit B &&
+	git reset --hard A &&
+	test_commit C &&
+
+	git checkout --orphan side &&
+	git rm -fr . &&
+	test_commit X &&
+	test_commit Y &&
+
+	test_tick && git merge --allow-unrelated-histories -m "M" B &&
+	test_tick && git merge -m "N" C &&
+	test_commit Z
+'
+
+test_expect_success 'log with boundary' '
+	git log --graph --boundary --format='%s' ^A ^X Z >actual &&
+	sed -e "s/Q$//" >expect <<-\EOF &&
+	* Z
+	*   N
+	|\  Q
+	| * C
+	* |   M
+	|\ \  Q
+	| * | B
+	| |/  Q
+	* | Y
+	o | X
+	 /  Q
+	o A
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'log --left-right with symmetric boundary' '
+	git log --graph --left-right --boundary --format='%s' B...C >actual &&
+	sed -e "s/Q$//" >expect <<-\EOF &&
+	> C
+	| < B
+	|/  Q
+	o A
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'log --left-right with asymmetric boundary' '
+	git log --graph --left-right --boundary --format='%s' ^A ^X Z >actual &&
+	sed -e "s/Q$//" >expect <<-\EOF &&
+	> Z
+	>   N
+	|\  Q
+	| > C
+	> |   M
+	|\ \  Q
+	| > | B
+	| |/  Q
+	> | Y
+	o | X
+	 /  Q
+	o A
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_failure 'log down to root' '
+	git log --graph --format='%s' Z >actual &&
+	sed -e "s/Q$//" >expect <<-\EOF &&
+	* Z
+	*   N
+	|\  Q
+	| * C
+	* |   M
+	|\ \  Q
+	| * | B
+	| |/  Q
+	| # A
+	* Y
+	# X
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_failure 'log down to root' '
+	git log --graph --format='%s' B Y >actual &&
+	sed -e "s/Q$//" >expect <<-\EOF &&
+	* Y
+	# X
+	* B
+	# A
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_failure 'log that happens to show root' '
+	git log --graph -3 --format='%s' B Y >actual &&
+	sed -e "s/Q$//" >expect <<-\EOF &&
+	* Y
+	# X
+	* B
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_failure 'log --left-right down to root' '
+	git log --graph --left-right --format='%s' B...Y >actual &&
+	sed -e "s/Q$//" >expect <<-\EOF &&
+	> Y
+	R X
+	< B
+	L A
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_failure 'log --left-right that happens to show root' '
+	git log --graph -3 --left-right --format='%s' B...Y >actual &&
+	sed -e "s/Q$//" >expect <<-\EOF &&
+	> Y
+	R X
+	< B
+	EOF
+	test_cmp expect actual
+'
+
+test_done
Junio C Hamano Jan. 17, 2021, 10:44 p.m. UTC | #2
Kyle Marek <kmarek@pdinc.us> writes:

> Subject: Re: [PATCH 1/2] revision: Denote root commits with '#'

Downcase "D"; this will stand out in "git shortlog --no-merges" for
a wrong reason otherwise.

> This aids in identifying where an unrelated branch history starts when
> using `git log --graph --oneline --all`

This is triggerd only with --show-linear-break option, when combined
with [2/2]?  I think that is a bug introduced in the next step.

> Signed-off-by: Kyle Marek <kmarek@pdinc.us>
> ---
>  revision.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/revision.c b/revision.c
> index 9dff845bed..8556923de8 100644
> --- a/revision.c
> +++ b/revision.c
> @@ -4191,9 +4191,11 @@ const char *get_revision_mark(const struct rev_info *revs, const struct commit *
>  			return "<";
>  		else
>  			return ">";
> -	} else if (revs->graph)
> +	} else if (revs->graph) {
> +		if (!commit->parents)
> +			return "#";
>  		return "*";
> -	else if (revs->cherry_mark)
> +	} else if (revs->cherry_mark)
>  		return "+";
>  	return "";
>  }
Kyle Marek Jan. 18, 2021, 7:56 a.m. UTC | #3
On 1/17/21 4:10 PM, Junio C Hamano wrote:
> Kyle Marek<kmarek@pdinc.us>  writes:
>
>> This aids in identifying where an unrelated branch history starts when
>> using `git log --graph --oneline --all`
>>
>> Signed-off-by: Kyle Marek<kmarek@pdinc.us>
>> ---
>>   revision.c | 6 ++++--
>>   1 file changed, 4 insertions(+), 2 deletions(-)
> No tests?

I'm not very familiar with the code base. I now see the t/README file.

>> diff --git a/revision.c b/revision.c
>> index 9dff845bed..8556923de8 100644
>> --- a/revision.c
>> +++ b/revision.c
>> @@ -4191,9 +4191,11 @@ const char *get_revision_mark(const struct rev_info *revs, const struct commit *
>>   			return "<";
>>   		else
>>   			return ">";
>> -	} else if (revs->graph)
>> +	} else if (revs->graph) {
>> +		if (!commit->parents)
>> +			return "#";
>>   		return "*";
>> -	else if (revs->cherry_mark)
>> +	} else if (revs->cherry_mark)
>>   		return "+";
>>   	return "";
>>   }
> Here is what I tried to come up with, but somehow the "#" marker is
> not showing for me.
>
> The "counted plus --left-right" tests stress why a single "#" is not
> good enough.  I think the patch also needs to replace "<" and ">"
> for root commits that are left and right---in the tests, I used "L"
> to denote "root that is on the left side" (and "R" for the right
> side) instead of single "#", so that we do not to lose information.
>
> By the way, as I already said in the original thread, I do not think
> the '#' marking is a good idea; I'd rather see the root commit shown
> by shifting columns.

Sorry, I wasn't subscribed to the list until Jason CC'd me on his 
request. I also wasn't aware of --left-right.

I'll investigate the revision-mark shifting idea. I am concerned that it 
would get complicated if a graph edge extends around a revision that 
needs to be shifted, but I'm finding it difficult to produce this with 
--graph:

*   8d82d0a (HEAD -> master) Merge branch 'o1'
|\
| * 3479914 (o1) O1
| * a674e07 O1        <-- root commit
| * 2237b52 (t) T
| * f525fa5 T
|/
* f15f936 A
| * 9e289ed (u) U
|/
* ee911c8 initial     <-- root commit

vs:

*   8ee9b14 (HEAD -> master) Merge branch 'u'
|\
| * ed1990f (u) U
* |   277f31c Merge branch 'o1'
|\ \
| * | eaa71bb (o1) O1
| * | 9203a43 O1      <-- root commit
|  /
| | * bc2c4d9 (t) T
| | * 2d3c03b T
| |/
|/|
* | 6a26183 A
|/
* da85ccf initial     <-- root commit
  

Thoughts? Will git ever graph something like:

*
|\
| *
* |
|\ \
| * | <-- root commit
| * | <-- some head
|/ /
* /
|/
*     <-- root commit
Junio C Hamano Jan. 18, 2021, 7:15 p.m. UTC | #4
Kyle Marek <kmarek@pdinc.us> writes:

> I'll investigate the revision-mark shifting idea. I am concerned that
> it would get complicated if a graph edge extends around a revision
> that needs to be shifted,...

The "current graph layout makes it harder to see where the root is"
problem has a natural solution: fix the graph layout so that the
root is easily visible.

I however think it is a much harder approach to solve than using a
different mark for root commits, and it is the reason why there have
been at least a few attempts in the past that did essentially the
same patch as yours, plus the "linear break" which we accepted.

> *   8d82d0a (HEAD -> master) Merge branch 'o1'
> |\
> | * 3479914 (o1) O1
> | * a674e07 O1        <-- root commit
> | * 2237b52 (t) T
> | * f525fa5 T
> |/
> * f15f936 A
> | * 9e289ed (u) U
> |/
> * ee911c8 initial     <-- root commit
>
> vs:
>
> *   8ee9b14 (HEAD -> master) Merge branch 'u'
> |\
> | * ed1990f (u) U
> * |   277f31c Merge branch 'o1'
> |\ \
> | * | eaa71bb (o1) O1
> | * | 9203a43 O1      <-- root commit
> |  /
> | | * bc2c4d9 (t) T
> | | * 2d3c03b T
> | |/
> |/|
> * | 6a26183 A
> |/
> * da85ccf initial     <-- root commit

Sorry, I am not quite sure what you are trying to illustrate with
the comparison between the above two.  The latter makes it clear
that 9203a43 and da85ccf do not have parents in the depicted part of
the history [*1*].

In the former one, does 2237b52 have no child in the depicted part of
the history, and is the problem that it appears as if it has a674e07
as a child?  I wonder if we can just shift them, either:

> *   8d82d0a (HEAD -> master) Merge branch 'o1'
> |\__
> |   * 3479914 (o1) O1
> |   * a674e07 O1        <-- root commit
> | * 2237b52 (t) T
> | * f525fa5 T
> |/
> * f15f936 A

or

> *   8d82d0a (HEAD -> master) Merge branch 'o1'
> |\
> | * 3479914 (o1) O1
> | * a674e07 O1        <-- root commit
> |   * 2237b52 (t) T
> | __* f525fa5 T
> |/
> * f15f936 A

Or we could punt to show it with an extra blank line, although it is
suboptimial.

> *   8d82d0a (HEAD -> master) Merge branch 'o1'
> |\
> | * 3479914 (o1) O1
> | * a674e07 O1        <-- root commit
> |
> | * 2237b52 (t) T
> | * f525fa5 T
> |/
> * f15f936 A


[Footnote]

*1* Stepping back a bit, I think concentrating too much on "is it
    root?" is a wrong way to think about the problem.  Suppose you
    have two histories, e.g. (time flows from left to right; A and X
    are roots)

            A---B
                 \
          X---Y---Z

    and doing "git log --graph --oneline Z" would show A, B, X, Y
    and Z.

    If it benefits to show "A" (and "X") specially in the graph,
    that would mean that the current algorithm would show some other
    commit after showing A (probably X if it goes in chronological
    order), and it probably is confusing because X is shown on the
    same column as A, when there is no parent-child relationship
    between them (A is root after all).

    We are trying to highlight that A is not a child of anybody by
    using '#' instead.

    But in a slightly modified graph:

          C
         /
        O---A---B
                 \
          X---Y---Z

    if you do "git log --graph --oneline C..Z", you should see the
    same commits listed as above (A, B, X, Y and Z), and most likely
    in the same order.

    So special casing by "Ah, A is a root commit, so let's show it
    with '#'" does not help, even though we are facing exactly the
    same problem in the latter graph.

    And the right way to look at it is "does A have any parent in
    the part of the history being shown?", not "does A have any
    parent?"  Then 'A' will get exactly the same treatment in the
    two examples, and the visual problem that makes A appear as if
    it has parent-child relationship with unrelated commit X goes
    away.
Junio C Hamano Jan. 18, 2021, 8:33 p.m. UTC | #5
Junio C Hamano <gitster@pobox.com> writes:

> [Footnote]
>
> *1* Stepping back a bit, I think concentrating too much on "is it
>     root?" is a wrong way to think about the problem.  Suppose you
>     have two histories, e.g. (time flows from left to right; A and X
>     are roots)

A shorter and more concrete example.  Start from an empty repository:

	$ git init
	$ git commit --allow-empty -m Aroot
	$ git checkout --orphan side
	$ git commit --allow-empty -m Xroot
	$ git log --all --graph --oneline
        * a1f7cb2 (HEAD -> side) Xroot
        * b6fb655 (master) Aroot

These depict two root commits, Aroot and Xroot, and no other
commits.  We do want to show that these two commits do not have
parent-child relationship at all, and your (and a few proposals made
by other in the past) solution was to show them both with "#".

Continuing in the same repository:

	$ git checkout --orphan another
	$ git commit --allow-empty -m Oroot
	$ git commit --allow-empty -m A
	$ git log --graph --oneline ^another^ another side
        * eddf116 (HEAD -> another) A
        * a1f7cb2 (side) Xroot

These depict two commits, A and Xroot, and no other commits.  We
also want to show that these two commits do not have parent-child
relationship at all, but if we paint Xroot with "#", it still makes
it appear that A is a child of Xroot.

>     And the right way to look at it is "does A have any parent in
>     the part of the history being shown?", not "does A have any
>     parent?"  Then 'A' will get exactly the same treatment in the
>     two examples, and the visual problem that makes A appear as if
>     it has parent-child relationship with unrelated commit X goes
>     away.

So the condition we saw in your patches, !commit->parents, which
attempted to see if it was root, needs to be replaced with a helper
function that checks if there is any parent that is shown in the
output.  Perhaps

	int no_interesting_parents(struct commit *commit)
	{
		struct commit_list *parents = commit->parents;

		while (parents) {
			if (!(parents->object.flags & UNINTERESTING))
				return 0;
			parents = parents->next;
		}
		return 1;
	}

or something like that should serve as a replacement, i.e.

	return !commit->parents ? "#" : "*";

would become

	return no_interesting_parents(commit) ? "#" : "*";

Hmm?
Kyle Marek Jan. 19, 2021, 7:43 a.m. UTC | #6
On 1/18/21 3:33 PM, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> [Footnote]
>>
>> *1* Stepping back a bit, I think concentrating too much on "is it
>>      root?" is a wrong way to think about the problem.  Suppose you
>>      have two histories, e.g. (time flows from left to right; A and X
>>      are roots)
> A shorter and more concrete example.  Start from an empty repository:
>
> 	$ git init
> 	$ git commit --allow-empty -m Aroot
> 	$ git checkout --orphan side
> 	$ git commit --allow-empty -m Xroot
> 	$ git log --all --graph --oneline
>          * a1f7cb2 (HEAD -> side) Xroot
>          * b6fb655 (master) Aroot
>
> These depict two root commits, Aroot and Xroot, and no other
> commits.  We do want to show that these two commits do not have
> parent-child relationship at all, and your (and a few proposals made
> by other in the past) solution was to show them both with "#".
>
> Continuing in the same repository:
>
> 	$ git checkout --orphan another
> 	$ git commit --allow-empty -m Oroot
> 	$ git commit --allow-empty -m A
> 	$ git log --graph --oneline ^another^ another side
>          * eddf116 (HEAD -> another) A
>          * a1f7cb2 (side) Xroot
>
> These depict two commits, A and Xroot, and no other commits.  We
> also want to show that these two commits do not have parent-child
> relationship at all, but if we paint Xroot with "#", it still makes
> it appear that A is a child of Xroot.
>
>>      And the right way to look at it is "does A have any parent in
>>      the part of the history being shown?", not "does A have any
>>      parent?"  Then 'A' will get exactly the same treatment in the
>>      two examples, and the visual problem that makes A appear as if
>>      it has parent-child relationship with unrelated commit X goes
>>      away.
> So the condition we saw in your patches, !commit->parents, which
> attempted to see if it was root, needs to be replaced with a helper
> function that checks if there is any parent that is shown in the
> output.  Perhaps
>
> 	int no_interesting_parents(struct commit *commit)
> 	{
> 		struct commit_list *parents = commit->parents;
>
> 		while (parents) {
> 			if (!(parents->object.flags & UNINTERESTING))
> 				return 0;
> 			parents = parents->next;
> 		}
> 		return 1;
> 	}
>
> or something like that should serve as a replacement, i.e.
>
> 	return !commit->parents ? "#" : "*";
>
> would become
>
> 	return no_interesting_parents(commit) ? "#" : "*";
>
> Hmm?

Okay, I see what you mean. Fixing --graph to avoid implying ancestry 
sounds like a better approach to me.

That being said, I spoke to Jason recently, and he expressed interest in 
optionally marking root commits so they are easy to search for in a 
graph with something like /# in `less`. I see value in this, too.

So would you be open to my modifying of the patch in question (patch 1+2 
squashed, I guess) to instead use "--mark-roots=<mark>" to optionally 
mark root commits with a string <mark>, and pursue fixing the --graph 
rendering issue in another series?

If so, what would you like to see out of the --left-right issue? Maybe 
"--mark-left-root=<mark>" and "--mark-right-root=<mark>", so multi-byte 
strings may be used? Can there be more than one root on either side? (so 
the option would use a plural "roots" instead of "root"?)
Junio C Hamano Jan. 19, 2021, 10:10 p.m. UTC | #7
Kyle Marek <kmarek@pdinc.us> writes:

>> So the condition we saw in your patches, !commit->parents, which
>> attempted to see if it was root, needs to be replaced with a helper
>> function that checks if there is any parent that is shown in the
>> output.
>> ...
>> Hmm?
>
> Okay, I see what you mean. Fixing --graph to avoid implying ancestry
> sounds like a better approach to me.

Sorry, I do not know how you drew that conclusion from my
description.

All I meant to convey is "roots are not special at all, commits that
do not have parents in the parts of the history shown are, and care
must be taken to ensure that they do not appear to have parents".

And the argument applies equally to either of two approaches.
Whether the solution chosen is

 (1) to use special set of markers "{#}" for commits that do not
     have parents in the displayed part of the history instead of
     the usual "<*>", or

 (2) to stick to the normal set of markers "<*>" but shift the graph
     to avoid false ancestry.

we shouldn't be special casing "root commits" just because they are
roots.  Exactly the same issue exists for non-root commits whose
parents are not shown in the output, if commits from unrelated
ancestry is drawn directly below them.

> That being said, I spoke to Jason recently, and he expressed interest
> in optionally marking root commits so they are easy to search for in a 
> graph with something like /# in `less`. I see value in this,

I do not mind to denote the "this commit may appear directly on top
of another commit, but there is no ancestry" situation with a
special set of markers that is different from the usual "<*>" (for
left, normal and right) set.  I agree pagers are good ways to /search
things in the output.

> So would you be open to my modifying of the patch in question (patch
> 1+2 squashed, I guess) to instead use "--mark-roots=<mark>" to
> optionally mark root commits with a string <mark>, and pursue fixing
> the --graph rendering issue in another series?

I do not mind if the graph rendering fix does not happen yet again;
IIRC the past contributors couldn't implement it, either.

I think this new feature should be made opt-in by introducing a new
option (without giving it a configuration variable), with explicit
"--no-<option>" supported to countermand a "--<option>=#" that may
appear earlier on the command line (or prepare your scripts for
later introduction of such a configuration variable).

I do find it troubling if the <option> has "root" in its name, and I
would find it even more troubling if the feature somehow treated
root commits specially but not other commits that do not have their
parents shown.  It was the primary point I wanted to stress in the
previous two message [*1*].

I am hoping that a single option can give three-tuple that replaces
the usual "<*>", with perhaps the default of "{#}" or something.

I however offhand do not think of a way to make "left root" appear
in the output, but because we'd need "right root" that looks
different from ">" anyway, it may make sense to allow specifying
"left root" just for symmetry.


[Footnote]

*1* But if we do not think of a good option name without the word
    "root" in it, I might be talked into a name with "root", as long
    as we clearly describe (1) that commits that has parents that
    are not shown in the history are also shown with these letters,
    and (2) that new contributors are welcome to try coming up with
    a new name for the option to explain the behaviour better, but
    are not welcome to argue that the option should special case
    root commits only because the option is named with "root" in it.
Kyle Marek Jan. 20, 2021, 3:25 a.m. UTC | #8
On 1/19/21 5:10 PM, Junio C Hamano wrote:
> Kyle Marek <kmarek@pdinc.us> writes:
>
>>> So the condition we saw in your patches, !commit->parents, which
>>> attempted to see if it was root, needs to be replaced with a helper
>>> function that checks if there is any parent that is shown in the
>>> output.
>>> ...
>>> Hmm?
>> Okay, I see what you mean. Fixing --graph to avoid implying ancestry
>> sounds like a better approach to me.
> Sorry, I do not know how you drew that conclusion from my
> description.
>
> All I meant to convey is "roots are not special at all, commits that
> do not have parents in the parts of the history shown are, and care
> must be taken to ensure that they do not appear to have parents".

Yeah, I guess I am confused. I thought "Fixing --graph to avoid implying 
ancestry" was reaching the same point as "care must be taken to ensure 
that [commits without parents shown] do not appear to have parents". (I 
wasn't just talking about root commits at that point)

> And the argument applies equally to either of two approaches.
> Whether the solution chosen is
>
>   (1) to use special set of markers "{#}" for commits that do not
>       have parents in the displayed part of the history instead of
>       the usual "<*>", or
>
>   (2) to stick to the normal set of markers "<*>" but shift the graph
>       to avoid false ancestry.
>
> we shouldn't be special casing "root commits" just because they are
> roots.  Exactly the same issue exists for non-root commits whose
> parents are not shown in the output, if commits from unrelated
> ancestry is drawn directly below them.

I understand. Coming back to the "root commit" situation below.

>> That being said, I spoke to Jason recently, and he expressed interest
>> in optionally marking root commits so they are easy to search for in a
>> graph with something like /# in `less`. I see value in this,
> I do not mind to denote the "this commit may appear directly on top
> of another commit, but there is no ancestry" situation with a
> special set of markers that is different from the usual "<*>" (for
> left, normal and right) set.  I agree pagers are good ways to /search
> things in the output.
>
>> So would you be open to my modifying of the patch in question (patch
>> 1+2 squashed, I guess) to instead use "--mark-roots=<mark>" to
>> optionally mark root commits with a string <mark>, and pursue fixing
>> the --graph rendering issue in another series?
> I do not mind if the graph rendering fix does not happen yet again;
> IIRC the past contributors couldn't implement it, either.
>
> I think this new feature should be made opt-in by introducing a new
> option (without giving it a configuration variable), with explicit
> "--no-<option>" supported to countermand a "--<option>=#" that may
> appear earlier on the command line (or prepare your scripts for
> later introduction of such a configuration variable).

Okay

> I do find it troubling if the <option> has "root" in its name, and I
> would find it even more troubling if the feature somehow treated
> root commits specially but not other commits that do not have their
> parents shown.  It was the primary point I wanted to stress in the
> previous two message [*1*].

I'll come back to this below.

> I am hoping that a single option can give three-tuple that replaces
> the usual "<*>", with perhaps the default of "{#}" or something.

I thought about that, but can we handle any of the three markers being 
multi-byte characters?

> I however offhand do not think of a way to make "left root" appear
> in the output, but because we'd need "right root" that looks
> different from ">" anyway, it may make sense to allow specifying
> "left root" just for symmetry.

I'm thinking on that one. I need to learn more about --left-right. I 
don't know how/when to use it yet.

> [Footnote]
>
> *1* But if we do not think of a good option name without the word
>      "root" in it, I might be talked into a name with "root", as long
>      as we clearly describe (1) that commits that has parents that
>      are not shown in the history are also shown with these letters,
>      and (2) that new contributors are welcome to try coming up with
>      a new name for the option to explain the behaviour better, but
>      are not welcome to argue that the option should special case
>      root commits only because the option is named with "root" in it.

So, on the root vs parents-not-shown commits issue:

You're right. Commits with their parents hidden by the range specifiers 
have the same graphing issue as root commits.

While root commits are not a special case in the sense that --graph 
makes ancestor implications for more than just root commits, root 
commits are a special case when we think about interpreting the presence 
of hidden lineage in --graph output.

Considering one of your examples:

           C
          /
         O---A---B
                  \
           X---Y---Z

When graphing C..Z, git produces output like:

*   0fbb0dc (HEAD -> z) Z
|\
| * 11be529 (master) B
| * 8dd1b85 A
* 851a915 Y
* 27d3ed0 (x) X

We cannot tell from the above graph alone that X is a root and A is not.

So I think it might be useful if I could do --mark-roots='#' 
--mark-hidden-lineage=$'\u22ef' (Unicode Midline Horizontal Ellipsis) to 
produce the following:

*   0fbb0dc (HEAD -> z) Z
|\
| * 11be529 (master) B
| ⋯ 8dd1b85 A
* 851a915 Y
# 27d3ed0 (x) X

Alternatively, it could be argued that --boundary can be used to 
indicate a hidden lineage, since root commits do not have boundary 
commits listed below them. But --boundary draws one more commit than 
necessary, and there still isn't an easy way to search for roots in the 
pager.

I understand that I am now leaving the original scope of the issue, but 
I think it is worth considering.

Of course, I would also like to try fixing the original graphing issue 
in general.

Thoughts?
Junio C Hamano Jan. 20, 2021, 6:47 a.m. UTC | #9
Kyle Marek <kmarek@pdinc.us> writes:

> When graphing C..Z, git produces output like:
>
> *   0fbb0dc (HEAD -> z) Z
> |\
> | * 11be529 (master) B
> | * 8dd1b85 A
> * 851a915 Y
> * 27d3ed0 (x) X
>
> We cannot tell from the above graph alone that X is a root and A is not.

I actually do not see that as a problem.  In the past several years,
I've never needed to see "log --graph" output that goes all the way
down to the roots, unless I was playing with a toy repository in
order to tweak and/or develop a feature in Git that draws the graph.

Besides, such root commtis in real life projects would not say "X",
but something along the lines of "my very initial commit", which
would be much more "/<search>" friendly to pagers than "#".

So, no, sorry, but I do not buy "root is more special" at all.

Thanks.
Jason Pyeron Jan. 20, 2021, 3:11 p.m. UTC | #10
> -----Original Message-----
> From: Junio C Hamano
> Sent: Wednesday, January 20, 2021 1:48 AM
> 
> Kyle Marek writes:
> 
> > When graphing C..Z, git produces output like:
> >
> > *   0fbb0dc (HEAD -> z) Z
> > |\
> > | * 11be529 (master) B
> > | * 8dd1b85 A
> > * 851a915 Y
> > * 27d3ed0 (x) X
> >
> > We cannot tell from the above graph alone that X is a root and A is not.
> 
> I actually do not see that as a problem.  In the past several years,
> I've never needed to see "log --graph" output that goes all the way

I respect your needs, but they conflict with others' needs, while this enhancement to resolve an ambiguity does not impede your needs and solves others' needs. Please do not impose your exclusive use cases upon everyone.

> down to the roots, unless I was playing with a toy repository in

I brought this issue up because several repositories in use have this issue. Two repositories immediately at hand have 35k+ and 2500+ commits each. These are repositories used by professionals and contain actual source code. ( I know your "toy repository" tone was not meant as an insult because I read your emails daily, Kyle may not have )

> order to tweak and/or develop a feature in Git that draws the graph.
> 
> Besides, such root commtis in real life projects would not say "X",
> but something along the lines of "my very initial commit", which

Here is where a fundamental (feature) issue of git rears its ugly head. You cannot fix the commit meta data (e.g. message) after the fact. Humans write the message, and it does not always write a message the is easily recognizable as such, no less easy to search.

> would be much more "/<search>" friendly to pagers than "#".

Here are some messages:

bug 2252 test case (e.g. for tomcat 9 with unpackWARs=false)
Add migrate-from-blackfat.sql
Initial commit from Create React App
parrent pom
initial commit
Base applet
intial
Initial commit
initial
import prod 
import prod sql 
import prod 
import coop/dev 
import prod CMIS.zip


Here we have commits without the word initial, initial misspelled, or in different case.

Let's not bike shed this issue. The left/right issues are a great catch from a peer review point of view.

I'll ask the following questions, besides the left right and test case issues:

What quality issues exists with the patch (e.g. bugs, strategy, etc)?

How can the proposed additional features be captured for future implementation?

Do we want to continue discussion on option naming?

Are there other questions to discuss?

Respectfully,

Jason Pyeron
Junio C Hamano Jan. 20, 2021, 9:52 p.m. UTC | #11
"Jason Pyeron" <jpyeron@pdinc.us> writes:

>> I actually do not see that as a problem.  In the past several years,
>> I've never needed to see "log --graph" output that goes all the way
>
> I respect your needs, but they conflict with others' needs, while
> this enhancement to resolve an ambiguity does not impede your
> needs and solves others' needs.

I am questioning if such "needs" really exist in the first place.

Among 35k+ commits in the example project, if you had more than a
few dozens of roots, then it may make sense to highlight them
differently from ordinary commits whether they have parents in the
shown part of the history.  It's like "log --decorate" shows branch
tips marked specially.

Yes, I am saying that such a "this is root" marking, if it is
valuable, should go on a part of "log --oneline" output that is
shown even without "--graph", just like we annotate the commit with
"(branch name)" in the output, instead of painting the commit in the
graph by replacing the '*' node with something else.

And how often do you really need to see commits near the root, say
the earliest 100 commits, in the 35k+ commit history?  Is it really
necessary to tell which among these 100 is the root?  What problem
does it solve?  Perhaps I am reacting to your solution without
seeing the problem you are trying to solve?  First, I took the
"replace <*> with {#}" as a solution for "parenthood becomes unclear
in the --graph output" problem, and pointed out that the solution
for that issue should apply to not just root commits but equally to
the ones above the boundary.

But it seems that I am hearing that it is not "graph showing false
parenthood" problem that you were trying to solve, but "I want to
see root differently for unspecified reason".

I am asking why, and if the reason is because there are nontrivial
number of them sprinkled throughout the history, I am offering my
opinion that something like how we show the commits at the tips of
branches and tagged ones would be a better model than changing the
letter used for the node in the graph.

> Here are some messages:
>
> bug 2252 test case (e.g. for tomcat 9 with unpackWARs=false)
> Add migrate-from-blackfat.sql
> Initial commit from Create React App
> parrent pom
> initial commit
> Base applet
> intial
> Initial commit
> initial
> import prod 
> import prod sql 
> import prod 
> import coop/dev 
> import prod CMIS.zip

You seem to have problems with not just root commits ;-)
How many of these 5 "initial" commits are root?

> I'll ask the following questions, besides the left right and test case issues:
>
> What quality issues exists with the patch (e.g. bugs, strategy, etc)?

By strategy I take that you mean design.  We've been talking about
it, right?  Until that gets more or less settled, line-by-line bug
hunting tends to become a waste of time, and I haven't had a chance
to afford extra review bandwidth to dedicate to this topic.

Now the problem being solved seems to be changing, so I am not sure
how close to be "done" the posted patch is to the real solution.
Sorry.
Jason Pyeron Jan. 20, 2021, 11:01 p.m. UTC | #12
Summary: --graph used with --oneline sometimes produces ambiguous output when more than one commit has no parents and are not yet merged

> From: Junio C Hamano
> Sent: Wednesday, January 20, 2021 4:52 PM
> 
> "Jason Pyeron" writes:
> 
> >> I actually do not see that as a problem.  In the past several years,
> >> I've never needed to see "log --graph" output that goes all the way
> >
> > I respect your needs, but they conflict with others' needs, while
> > this enhancement to resolve an ambiguity does not impede your
> > needs and solves others' needs.
> 
> I am questioning if such "needs" really exist in the first place.
> 
> Among 35k+ commits in the example project, if you had more than a
> few dozens of roots, then it may make sense to highlight them
> differently from ordinary commits whether they have parents in the
> shown part of the history.  It's like "log --decorate" shows branch
> tips marked specially.

That could work too.

> 
> Yes, I am saying that such a "this is root" marking, if it is
> valuable, should go on a part of "log --oneline" output that is
> shown even without "--graph", just like we annotate the commit with

I do not have any preferences beyond not "being lied to by git graph".

| * 22222
| * 11111
| * 33333
| * 44444

Implies that 11111 and 33333 have a parent / child relationship.

Quoting the man page, "--graph Draw a text-based graphical representation of the commit history on the left hand side of the output. This may cause extra lines to be printed in between commits, in order for the graph history to be drawn properly", would be preferable to add blank lines.

> "(branch name)" in the output, instead of painting the commit in the
> graph by replacing the '*' node with something else.
> 
> And how often do you really need to see commits near the root, say
> the earliest 100 commits, in the 35k+ commit history?  Is it really
> necessary to tell which among these 100 is the root?  

Yes, and the assumption that they are at the beginning is flawed too.

$ git log --oneline --graph --all | cat -n | egrep $(git rev-list --max-parents=0 --all | cut -c 1-8 | tr '\n' '|' | head -c -1)
    87  | | * be2c70b7 bug 2252 test case (e.g. for tomcat 9 with unpackWARs=false)
  2161  | | * 8ef73128 Add migrate-from-blackfat.sql
  2164  | | * 5505e019 initial
  2235  | | | | | | | | | | | | | * 83337c67 intial
  2921  | | | | * ca14dc49 Initial commit
  2931  | | | * cbdce824 initial commit
  2963  | | * 8f1828c1 Base applet
  2971  | * 658af21f parrent pom
  3026  * 8356af31 Initial commit from Create React App

git log --oneline --graph produces 3026 lines in this example.

> What problem does it solve?  

Avoiding confusion and non-compliance with the man page, which wastes human's time.

> Perhaps I am reacting to your solution without
> seeing the problem you are trying to solve?  First, I took the
> "replace <*> with {#}" as a solution for "parenthood becomes unclear
> in the --graph output" problem, and pointed out that the solution
> for that issue should apply to not just root commits but equally to
> the ones above the boundary.
> 

I have no objection to that either as it neither helps or hinders the solution to the real and initial issue.

> But it seems that I am hearing that it is not "graph showing false
> parenthood" problem that you were trying to solve, 

It is that graph is implying false parenthood. There was no intention for that (only) issue to morph.

> but "I want to
> see root differently for unspecified reason".

There is only one reason, the same reason that prompted the original email. Adjacent commits in the --graph formatted output were connected when they are actually not connected.

To quote earlier > From: Junio C Hamano
> Sent: Thursday, January 14, 2021 8:12 PM
> > | | | *  5505e019c2 2014-07-09 initial xxxxxx@xxxx
> > | | |
> > | | | *  3e658f4085 2019-09-10 (wiki/wip-citest, origin/wip-citest) Added defau
> > | | | *  ad148aafe6 2019-09-10 Added default CI/CD Jenkinsfile (from f7daf088)
> >
> ... is not so great in that it wastes a line, and the break
> won't be as noticeable when --graph is *not* used with --oneline.

No, because there would be no line connecting it.

| | | Date:   Tue Sep
| | |
| | |     Added defau
| | |
| | * commit 5505e019
| |   Author: xxxx
| |   Date:   Wed Jul
| |
| |       initial
| |
| | * commit 3e658f40
| | | Author: xxxx
| | | Date:   Tue Sep
| | |
| | |     Added defau
| | |
| | * commit ad148aaf
| | | Author: xxxx
| | | Date:   Tue Sep
| | |
| | |     Added defau
| | |

And to quote earlier > From: Junio C Hamano
> Sent: Thursday, January 14, 2021 8:12 PM
> > | | | #  5505e019c2 2014-07-09 initial xxxxxx@xxxx
> > | | | *  3e658f4085 2019-09-10 (wiki/wip-citest, origin/wip-citest) Added defau
> > | | | *  ad148aafe6 2019-09-10 Added default CI/CD Jenkinsfile (from f7daf088)
> This latter variant won't work.  Imagine we are showing --left-right
> for example.  Which side does '#' belong to?

There was no concerns or aversions about left/right. It was later clarified that being able to use the pagers search would be nice.

> 
> I am asking why, and if the reason is because there are nontrivial
> number of them sprinkled throughout the history, I am offering my
> opinion that something like how we show the commits at the tips of
> branches and tagged ones would be a better model than changing the
> letter used for the node in the graph.

Happy to take that solution too, but does it fix the bug in the graph when used with --oneline? And don’t misunderstand me, this is a bug in --graph with --oneline.

> 
> > Here are some messages:
> >
> > bug 2252 test case (e.g. for tomcat 9 with unpackWARs=false)
> > Add migrate-from-blackfat.sql
> > Initial commit from Create React App
> > parrent pom
> > initial commit
> > Base applet
> > intial
> > Initial commit
> > initial
> > import prod
> > import prod sql
> > import prod
> > import coop/dev
> > import prod CMIS.zip
> 
> You seem to have problems with not just root commits ;-)
> How many of these 5 "initial" commits are root?

100%, it was from:

git log --oneline $(git rev-list --max-parents=0 --all) | cut -c 10-

> 
> > I'll ask the following questions, besides the left right and test case issues:
> >
> > What quality issues exists with the patch (e.g. bugs, strategy, etc)?
> 
> By strategy I take that you mean design.  We've been talking about
> it, right?  Until that gets more or less settled, line-by-line bug
> hunting tends to become a waste of time, and I haven't had a chance
> to afford extra review bandwidth to dedicate to this topic.
> 
> Now the problem being solved seems to be changing, so I am not sure
> how close to be "done" the posted patch is to the real solution.
> Sorry.

There was no intention for change, but adjustments were made based on feedback. For example, quoting earlier > From: Junio C Hamano
> Sent: Thursday, January 14, 2021 8:12 PM
> It would be great to show it more like this:
> 
>  | | |   * 5505e019c2 2014-07-09 initial xxxxxx@xxxx
>  | | | *  3e658f4085 2019-09-10 (wiki/wip-citest, origin/wip-citest) Added defau
>  | | | *  ad148aafe6 2019-09-10 Added default CI/CD Jenkinsfile (from f7daf088)
> 

> From: Junio C Hamano
> Sent: Tuesday, January 19, 2021 5:10 PM
> 
> I do not mind if the graph rendering fix does not happen yet again;
> IIRC the past contributors couldn't implement it, either.

This was a good idea, but not readily feasible.

So to close the loop, I would love to support the creation and integration of a patch to ensure "graph history s/to be/is/ drawn properly" and not lying to the reader of the graph about the ancestry.

And thank you for spending time on this thread, I think we can find a feasible and usable solution.
Junio C Hamano Jan. 23, 2021, 6:07 p.m. UTC | #13
"Jason Pyeron" <jpyeron@pdinc.us> writes:

> Summary: --graph used with --oneline sometimes produces ambiguous
> output when more than one commit has no parents and are not yet
> merged
> ...
>> "(branch name)" in the output, instead of painting the commit in the
>> graph by replacing the '*' node with something else.
>> 
>> And how often do you really need to see commits near the root, say
>> the earliest 100 commits, in the 35k+ commit history?  Is it really
>> necessary to tell which among these 100 is the root?  
>
> Yes, and the assumption that they are at the beginning is flawed too.
>
> $ git log --oneline --graph --all | cat -n | egrep $(git rev-list --max-parents=0 --all | cut -c 1-8 | tr '\n' '|' | head -c -1)
>     87  | | * be2c70b7 bug 2252 test case (e.g. for tomcat 9 with unpackWARs=false)
>   2161  | | * 8ef73128 Add migrate-from-blackfat.sql
>   2164  | | * 5505e019 initial
>   2235  | | | | | | | | | | | | | * 83337c67 intial
>   2921  | | | | * ca14dc49 Initial commit
>   2931  | | | * cbdce824 initial commit
>   2963  | | * 8f1828c1 Base applet
>   2971  | * 658af21f parrent pom
>   3026  * 8356af31 Initial commit from Create React App
>
> git log --oneline --graph produces 3026 lines in this example.

Hmph.  Are you saying that you have 3000+ root commits in the 35k+
history?

Whether we add '[root]' decoration to the true roots (like
'(branchname)' decoration we add to branch tips), or painted '*' in
a different color (like '#'), you do not have to look for 'initial',
so having that many roots will not be a problem per-se with respect
to the "log" output, but there must be something strange going on.

I am not going to ask you why you need so many roots, because I
suspect that I will regret asking ;-).

By the way, I sense that your problem description is flip-flopping
again and I can no longer keep track of.  The way I read the message
I got from Kyle was, even when a graph has two commits that have no
parents in the visible part of the history, either Kyle wanted (or
Kyle got an impression after talking to you that you wanted) to see
these differently if one of them is a root and the other is non-root
(but happens to have none of its parents shown due to A..B range).
And that is why I started asking how meaningful to special case only
"root".

Now the message from you I am responding to in the "Sumary" above
says that it is not "root" but is about the placement of graph
nodes.

So, I dunno, with changing the description of the goalpost.  Now it
is that "root" is so not special at all and we only care about that
the a commit, none of whose parents are in the part of the shown
history, is shown in such a way that the user can tell that any
unrelated commits shown in the graph near it are not parents of such
a commit?  Or do you still want to show such a commit in two ways,
one for root and one for the ones above the boundary?
Jason Pyeron Jan. 23, 2021, 11:02 p.m. UTC | #14
> -----Original Message-----
> From: Junio C Hamano <gitster@pobox.com>
> Sent: Saturday, January 23, 2021 1:07 PM
> 
> "Jason Pyeron" writes:
> 
> > Summary: --graph used with --oneline sometimes produces ambiguous
> > output when more than one commit has no parents and are not yet
> > merged
> > ...
> >> "(branch name)" in the output, instead of painting the commit in the
> >> graph by replacing the '*' node with something else.
> >>
> >> And how often do you really need to see commits near the root, say
> >> the earliest 100 commits, in the 35k+ commit history?  Is it really
> >> necessary to tell which among these 100 is the root?
> >
> > Yes, and the assumption that they are at the beginning is flawed too.
> >
> > $ git log --oneline --graph --all | cat -n | egrep $(git rev-list --max-parents=0 --all | cut -c 1-8
> | tr '\n' '|' | head -c -1)
> >     87  | | * be2c70b7 bug 2252 test case (e.g. for tomcat 9 with unpackWARs=false)
> >   2161  | | * 8ef73128 Add migrate-from-blackfat.sql
> >   2164  | | * 5505e019 initial
> >   2235  | | | | | | | | | | | | | * 83337c67 intial
> >   2921  | | | | * ca14dc49 Initial commit
> >   2931  | | | * cbdce824 initial commit
> >   2963  | | * 8f1828c1 Base applet
> >   2971  | * 658af21f parrent pom
> >   3026  * 8356af31 Initial commit from Create React App
> >
> > git log --oneline --graph produces 3026 lines in this example.
> 
> Hmph.  Are you saying that you have 3000+ root commits in the 35k+
> history?
> 

I think you misread the specific example of 9 roots in 3026 commits, distributed throughout history.

> Whether we add '[root]' decoration to the true roots (like
> '(branchname)' decoration we add to branch tips), or painted '*' in
> a different color (like '#'), you do not have to look for 'initial',
> so having that many roots will not be a problem per-se with respect
> to the "log" output, but there must be something strange going on.
> 
> I am not going to ask you why you need so many roots, because I
> suspect that I will regret asking ;-).
> 
> By the way, I sense that your problem description is flip-flopping
> again and I can no longer keep track of.  The way I read the message
> I got from Kyle was, even when a graph has two commits that have no
> parents in the visible part of the history, either Kyle wanted (or
> Kyle got an impression after talking to you that you wanted) to see
> these differently if one of them is a root and the other is non-root
> (but happens to have none of its parents shown due to A..B range).
> And that is why I started asking how meaningful to special case only
> "root".
> 

I may be having trouble with my writing, apologies.

Here is the issue (bug):

1. I never want to see a commit implied to be the parent of an unrelated commit.
2. I never want to see a commit implied to be the child of an unrelated commit.

--graph --oneline is broken with regards to the man page and my desire to not be confused by the implication of relationship for inappropriately connected nodes on the graph.

| | * 1234567 commit child of 2345678
| | * 2345678 the first commit, having no parent
| | * 9876543 an unrelated commit and child of 8765432
| | * 8765432 ...

> Now the message from you I am responding to in the "Sumary" above
> says that it is not "root" but is about the placement of graph
> nodes.
> 

One and the same issue. Placing an * directly above another * is the issue.

Solution #1

| | * 1234567 commit child of 2345678
| | # 2345678 the first commit, having no parent
| | * 9876543 an unrelated commit and child of 8765432
| | * 8765432 ...

Or

Solution #2

| | * 1234567 commit child of 2345678
| | * 2345678 the first commit, having no parent
| |
| | * 9876543 an unrelated commit and child of 8765432
| | * 8765432 ...

Or

Solution #3

| | * 1234567 commit child of 2345678
| | \
| |  * 2345678 the first commit, having no parent
| | * 9876543 an unrelated commit and child of 8765432
| | * 8765432 ...

All of these solutions will solve the bug. #1 seems to be the easiest and becomes searchable. You have indicated that #3 others have failed to do so. #2 is very much aligned to the --graph without --oneline

> So, I dunno, with changing the description of the goalpost.  Now it
> is that "root" is so not special at all and we only care about that
> the a commit, none of whose parents are in the part of the shown
> history, is shown in such a way that the user can tell that any
> unrelated commits shown in the graph near it are not parents of such
> a commit?  Or do you still want to show such a commit in two ways,
> one for root and one for the ones above the boundary?

A commit without a parent is special - it has no parent. This means it has no history beyond that point. Something special happened at that time - the birth of new source code in source control.

Hopefully, I have cleared up the ambiguous wording.
Junio C Hamano Jan. 23, 2021, 11:45 p.m. UTC | #15
"Jason Pyeron" <jpyeron@pdinc.us> writes:

> One and the same issue. Placing an * directly above another * is the issue.

OK, I re-read the messages in the thread, and it appears that this
part from Kyle

>>>   
>>>             C
>>>            /
>>>           O---A---B
>>>                    \
>>>             X---Y---Z
>>>   
>>>   When graphing C..Z, git produces output like:
>>>   
>>>   *   0fbb0dc (HEAD -> z) Z
>>>   |\
>>>   | * 11be529 (master) B
>>>   | * 8dd1b85 A
>>>   * 851a915 Y
>>>   * 27d3ed0 (x) X
>>>   
>>>   We cannot tell from the above graph alone that X is a root and A is not.

was the only thing that argued that A and X (if the graph drawing
happend to place an unrelated commit immediately below it) should be
drawn differently so that you can tell X (root) and A (non root)
apart.

And you are saying (and it seems that you have consistently been
saying) that it is OK to draw A and X (again if other unrelated
commits were immediately drawn below them) the same way.  So I guess
all is well.  We do not have to use more 6 different symbols ("{#}"
to show commit above boundary, three more to show roots) but need to
introduce only three, if we were to go with the Solution #1 route.

It seems to me that Solution #2 is a special case of Solution #3 ;-)
They are both direct answers to the "graph drawn incorrectly can
imply ancestry that does not exist" problem.

Adding the "--decorate-roots" option that annotates the root commits
in the "git log" output can still be done, but that is an orthogonal
issue.  It does solve, together with any one of three options you
presented, the issue Kyle brought up, I would think.

Thanks.
Jason Pyeron Jan. 24, 2021, 12:02 a.m. UTC | #16
> From: Junio C Hamano
> Sent: Saturday, January 23, 2021 6:45 PM
> 
> "Jason Pyeron" writes:
> 
> > One and the same issue. Placing an * directly above another * is the issue.
> 
> OK, I re-read the messages in the thread, and it appears that this
> part from Kyle
> 

Added more of the context below.

> >>>   While root commits are not a special case in the sense that --graph 
> >>>   makes ancestor implications for more than just root commits, root 
> >>>   commits are a special case when we think about interpreting the presence 
> >>>   of hidden lineage in --graph output.
> >>>   
> >>>   Considering one of your examples:
> >>>
> >>>             C
> >>>            /
> >>>           O---A---B
> >>>                    \
> >>>             X---Y---Z
> >>>
> >>>   When graphing C..Z, git produces output like:
> >>>
> >>>   *   0fbb0dc (HEAD -> z) Z
> >>>   |\
> >>>   | * 11be529 (master) B
> >>>   | * 8dd1b85 A
> >>>   * 851a915 Y
> >>>   * 27d3ed0 (x) X
> >>>
> >>>   We cannot tell from the above graph alone that X is a root and A is not.

This was a side track down the left right issue. I personally feel that using the left right features is a buyer beware situation.

> 
> was the only thing that argued that A and X (if the graph drawing
> happend to place an unrelated commit immediately below it) should be
> drawn differently so that you can tell X (root) and A (non root)
> apart.
> 
> And you are saying (and it seems that you have consistently been
> saying) that it is OK to draw A and X (again if other unrelated

I am neither saying or not saying that - partial graph issues are outside of my concerns. Kyle was attempting to reconcile comments on this list about partial graph rendering when his patch was submitted.

> commits were immediately drawn below them) the same way.  So I guess
> all is well.  We do not have to use more 6 different symbols ("{#}"
> to show commit above boundary, three more to show roots) but need to
> introduce only three, if we were to go with the Solution #1 route.

Honestly, I do not care about the <>{}. Whatever makes sense.

> 
> It seems to me that Solution #2 is a special case of Solution #3 ;-)
> They are both direct answers to the "graph drawn incorrectly can
> imply ancestry that does not exist" problem.
> 
> Adding the "--decorate-roots" option that annotates the root commits
> in the "git log" output can still be done, but that is an orthogonal
> issue.  It does solve, together with any one of three options you
> presented, the issue Kyle brought up, I would think.
> 

Yes, adding --decorate-roots to add more wide descriptive text before the message would do it, but it is the worst solution #4.

> Thanks.
Junio C Hamano Jan. 25, 2021, 7 a.m. UTC | #17
"Jason Pyeron" <jpyeron@pdinc.us> writes:

>> It seems to me that Solution #2 is a special case of Solution #3 ;-)
>> They are both direct answers to the "graph drawn incorrectly can
>> imply ancestry that does not exist" problem.
>> 
>> Adding the "--decorate-roots" option that annotates the root commits
>> in the "git log" output can still be done, but that is an orthogonal
>> issue.  It does solve, together with any one of three options you
>> presented, the issue Kyle brought up, I would think.
>
> Yes, adding --decorate-roots to add more wide descriptive text
> before the message would do it, but it is the worst solution #4.

I said that "--decorate-roots" is a solution to an orthogonal issue.

Let's recall the C..Z example that shows A (non-root) and X (root)
in several messages back.  Either can be drawn with unrelated commit
immediately below them, depending on the topology of other commits
(imagine there is another commit M that is not related to any of the
commits connected to A or Z, and it is given to "git log C..Z M"; if
we draw C..Z part first and then draw O after it, M would most
likely come immediately after X.

(history: time flows left to right)

          C
         /
        O---A---B
                 \
          X---Y---Z

        M

(log --graph output: time flows bottom to top)

    *   0fbb0dc (HEAD -> z) Z
    |\
    | * 11be529 (master) B
    | * 8dd1b85 A
    * 851a915 Y
    * 27d3ed0 [root] X
    * 1111111 M

Now, the earlier C..Z example I happened to draw B and A first
before drawing Y and X, but if we swap the merge order of Z, it is
likely that the graph output would draw Y and X and then B and A.
"git log C..Z M" in such a history would likely to show M directly
below A (non-root).

    *   0fbb0dc (HEAD -> z) Z
    |\
    | * 851a915 Y
    | * 27d3ed0 [root] X
    * 11be529 (master) B
    * 8dd1b85 A
    * 1111111 M

In short, the [root] annotation does not, and it is not meant to,
solve the "misleading graph" issue.

It only solves "root is special, with or without --graph" issue
(such an issue may or may not exist).
diff mbox series

Patch

diff --git a/revision.c b/revision.c
index 9dff845bed..8556923de8 100644
--- a/revision.c
+++ b/revision.c
@@ -4191,9 +4191,11 @@  const char *get_revision_mark(const struct rev_info *revs, const struct commit *
 			return "<";
 		else
 			return ">";
-	} else if (revs->graph)
+	} else if (revs->graph) {
+		if (!commit->parents)
+			return "#";
 		return "*";
-	else if (revs->cherry_mark)
+	} else if (revs->cherry_mark)
 		return "+";
 	return "";
 }