Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-20 Thread Scott Schmit
On Mon, Mar 16, 2015 at 11:53:08AM -0700, Junio C Hamano wrote:
 Because the history is not linear in Git, bisection works by
 shrinking a subgraph of the history DAG that contains yet to be
 tested, suspected to have introduced a badness commits.  The
 subgraph is defined as anything reachable from _the_ bad commit
 (initially, the one you give to the command when you start) that are
 not reachable from any of the good commits.
 
 Suppose you started from this graph.  Time flows left to right as
 usual.
 
   ---0---2---4---6---8---9
   \ /
1---3---5---7
 
 Then mark the initial good and bad commits as G and B.
 
   ---G---2---4---6---8---B
   \ /
1---3---5---7
 
 And imagine that you are asked to check 4, which turns out to be
 good.  We do not _move_ G to 4; we mark 4 as good, while keeping
 0 also as good.
 
   ---G---2---G---6---8---B
   \ /
1---3---5---7
 
 And if you are next asked to check 5, and mark it as good, the graph
 will become like this:
 
   ---G---2---G---6---8---B
   \ /
1---3---G---7
 
 Of course, at this point, the subgraph of suspects are 6, 7, 8 and
 9, and the subgraph no longer is affected by the fact that 0 is
 good.  But it is crucial to keep 0 marked as good in the step before
 this one, before you tested 5, as that is what allows us not having
 to test any ancestors of 0 at all.
 
 Now, one may wonder why we need multiple good commits but we do
 not need multiple bad commits.  This comes from the nature of
 bisection, which is a tool to find a _single_ breakage [*1*], and
 a fundamental assumption is that a breakage does not fix itself.
 
 Hence, if you have a history that looks like this:
 
 
G...1---2---3---4---6---8---B
 \
  5---7---B
 
 it follows that 4 must also be bad.  It used to be good long time
 ago somewhere before 1, and somewhere along way on the history,
 there was a single breakage event that we are hunting for.  That
 single event cannot be 5, 6, 7 or 8 because breakage at say 5 would
 not explain why the tip of the upper branch is broken---its breakage
 has no way to propagate there.  The breakage must have happened at 4
 or before that commit.

But what if 7  8 are the same patch, cherry-picked?  Or nearly the same
patch, but with some conflict resolution?

Couldn't that lead to the case that 4, 5, and 6 are good, while 7  8
are bad?  Or does that violate the single breakage rule in a way that
might be too subtle for some users?

-- 
Scott Schmit


smime.p7s
Description: S/MIME cryptographic signature


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-19 Thread Philip Oakley

From: Junio C Hamano gits...@pobox.com
Sent: Tuesday, March 17, 2015 6:33 PM

Christian Couder christian.cou...@gmail.com writes:

On Mon, Mar 16, 2015 at 10:05 PM, Junio C Hamano gits...@pobox.com 
wrote:



However, you can say git bisect bad rev (and git bisect good
rev for that matter) on a rev that is unrelated to what the
current bisection state is.  E.g. after you mark the child of 8 as
bad, the bisected graph would become

   G...1---2---3---4---6---8---B

and you would be offered to test somewhere in the middle, say, 4.
But it is perfectly OK for you to respond with git bisect bad 7,
if you know 7 is bad.

I _think_ the current code blindly overwrites the bad pointer,
making the bisection state into this graph if you do so.

   G...1---2---3---4
\
 5---B


Yes, we keep only one bad pointer.


This is very suboptimal.  The side branch 4-to-7 could be much
longer than the original trunk 4-to-the-tip, in which case we would
have made the suspect space _larger_, not smaller.


Yes, but the user is supposed to not change the bad pointer for no
good reason.


That is irrelevant, no?  Nobody is questioning that the user is
supposed to judge if a commit is good or bad correctly.

[...]

and/or we could make git bisect bad accept any number of bad
commitishs.


Yes, that is exactly what I meant.

The way I understand the Philip's point is that the user may have
a-priori knowledge that a breakage from the same cause appears in
both tips of these branches.


Just to clarify; my initial query followed on from the way Junio had 
described it with having two tips which were known bad. I hadn't been 
aware of how the bisect worked on a DAG, so I wanted to fully understand 
Junio's comment regarding the expectation of a clean jump to commit 4 
(i.e. shouldn't we test commit 4 before assuming it's actually bad).  I 
was quite happy with a bisect of a linear list, but was unsure about how 
Git dissected DAGs.


I can easily see cases in more complicated product branching where users 
report intermittent operation for various product variants (especially 
if modular) and one wants to seek out those commits that introduced the 
behavious (which is typically some racy condition - otherwise it would 
be deterministic).


Given Junio's explantion with the two bad commits (on different legs) 
I'd sort of assumed it could be both user given, or algorithmically 
determined as part of the bisect.



In such a case, we can start bisection
after marking the merge-base of two 'bad' commits, e.g. 4 in the
illustration in the message you are responding to, instead of
including 5, 6, and 8 in the suspect set.

You need to be careful, though.  An obvious pitfall is what you
should do when there is a criss-cross merge.


You end up with possibly two (or more) merges being marked as the source 
of the bad behaviour, especially when racy ;-)




Thanks.
--


Hope that helps.
Philip

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-18 Thread Christian Couder
On Tue, Mar 17, 2015 at 9:46 PM, Junio C Hamano gits...@pobox.com wrote:
 Christian Couder christian.cou...@gmail.com writes:

 On Tue, Mar 17, 2015 at 7:33 PM, Junio C Hamano gits...@pobox.com wrote:
 Christian Couder christian.cou...@gmail.com writes:

 Yes, but the user is supposed to not change the bad pointer for no
 good reason.

 That is irrelevant, no?  Nobody is questioning that the user is
 supposed to judge if a commit is good or bad correctly.

 So if there is already a bad commit and the user gives another
 bad commit, that means that the user knows that it will replace the
 existing bad commit with the new one and that it's done for this
 purpose.

 ECANNOTQUITEPARSE.  The user may say git bisect bad $that and we
 do not question $that is bad. Git does not know better than the
 user.

 But that does not mean Git does not know better than the user how
 the current bad commit and $that commit are related.  The user is
 not interested in replacing at all.  The user is telling just one
 single fact, that is, $that is bad.

The user may make mistakes and try to fix them, like for example:

$ git checkout master
$ git bisect bad
$ git log --oneline --decorate --graph --all
# Ooops I was not on the right branch
$ git checkout dev
$ git bisect bad
$ git log --oneline --decorate --graph --all
# Everything looks ok now; the bad commit is what I expect
# I can properly continue bisecting using git bisect good...

In this case the user, who knows how git bisect works, expected that
the second git bisect bad would fix the previous mistake made using
the first git bisect bad.

If we make git bisect bad behave in another way we may break an
advanced user's expectation.

 I am not quite sure if I am correctly getting what you meant to say,
 but if you meant only when --alternate is given, we should do the
 merge-base thing; we should keep losing the current 'bad' and
 replace it with the new one without the --alternate option, I would
 see that as an exercise of a bad taste.

 What I wanted to say is that if we change git bisect bad commitish,
 so that now it means add a new bad commit instead of the previous
 replace the current bad commit, if any, with this one, then experienced
 users might see that change as a regression in the user interface and
 it might even break scripts.

 Huh?

 Step back a bit.  The place you need to start from is to admit the
 fact that what git bisect bad committish currently does is
 broken.

 Try creating this history yourself

 a---b---c---d---e---f

 and start bisection this way:

 $ git bisect start f c
 $ git bisect bad a

 Immediately after the second command, git bisect moans

 Some good revs are not ancestor of the bad rev.
 git bisect cannot work properly in this case.
 Maybe you mistake good and bad revs?

 when it notices that the good rev (i.e. 'c') is no longer an
 ancestor of the 'bad', which now points at 'a'.

 But that is because git bisect bad _blindly_ moved 'bad' that used
 to point at 'f' to 'a', making a good rev (i.e. 'c') an ancestor of
 the bad rev, without even bothering to check.

Yeah, git bisect bad currently does what it is asked and then
complains when it looks like a mistake has been made.

You might see that as a bug. I am seeing that more as git bisect
expecting users to know what they are doing.

For example an advanced user might have realized that the first git
bisect start f c was completely rubish for some reason, and the git
bisect bad a might be a first step to fix that. (The next step might
then be deleting the good pointer...)

 Now, if we fixed this bug and made the bisect_state function more
 careful (namely, when accepting bad, make sure it is not beyond
 any existing good, or barf like the above, _without_ moving the
 bad pointer), the user interface and behaviour would be changed.  Is
 that a regression?  No, it is a usability fix and a progress.

Yeah, you might see that as a usability fix and a progress.

 Simply put, bisect_state function can become more careful and
 intelligent to help users.

Yeah, we can try to help users more, but doing that we might annoy
some advanced users,  who are used to the current way git bisect
works, and perhaps break some scripts.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-17 Thread Christian Couder
On Tue, Mar 17, 2015 at 7:33 PM, Junio C Hamano gits...@pobox.com wrote:
 Christian Couder christian.cou...@gmail.com writes:

 On Mon, Mar 16, 2015 at 10:05 PM, Junio C Hamano gits...@pobox.com wrote:

 However, you can say git bisect bad rev (and git bisect good
 rev for that matter) on a rev that is unrelated to what the
 current bisection state is.  E.g. after you mark the child of 8 as
 bad, the bisected graph would become

G...1---2---3---4---6---8---B

 and you would be offered to test somewhere in the middle, say, 4.
 But it is perfectly OK for you to respond with git bisect bad 7,
 if you know 7 is bad.

 I _think_ the current code blindly overwrites the bad pointer,
 making the bisection state into this graph if you do so.

G...1---2---3---4
 \
  5---B

 Yes, we keep only one bad pointer.

 This is very suboptimal.  The side branch 4-to-7 could be much
 longer than the original trunk 4-to-the-tip, in which case we would
 have made the suspect space _larger_, not smaller.

 Yes, but the user is supposed to not change the bad pointer for no
 good reason.

 That is irrelevant, no?  Nobody is questioning that the user is
 supposed to judge if a commit is good or bad correctly.

So if there is already a bad commit and the user gives another
bad commit, that means that the user knows that it will replace the
existing bad commit with the new one and that it's done for this
purpose.

 And nobody sane is dreaming that Git could do better and detect
 user's mistakes when the user says 'bad' for a commit that is
 actually 'good'; if Git can do that, then it should be able to do
 the bisect without any user input (including bisect run) at all
 ;-).

 We certainly should be able to take advantage of the fact that the
 current bad commit (i.e. the child of 8) and the newly given bad
 commit (i.e. 7) are both known to be bad and mark 4 as bad instead
 when that happens, instead of doing the suboptimal thing the code
 currently does.

 Yeah, we could do that, but we would have to allow it only if a
 special option is passed on the command line, for example:
 git bisect bad --alternate commitish

 I am not quite sure if I am correctly getting what you meant to say,
 but if you meant only when --alternate is given, we should do the
 merge-base thing; we should keep losing the current 'bad' and
 replace it with the new one without the --alternate option, I would
 see that as an exercise of a bad taste.

What I wanted to say is that if we change git bisect bad commitish,
so that now it means add a new bad commit instead of the previous
replace the current bad commit, if any, with this one, then experienced
users might see that change as a regression in the user interface and
it might even break scripts.

That's why I suggested to use a new option to mean
add a new bad commit, though --alternate might not be the best
name for this option.

 Because the merge-base thing is using both the current and the new
 one, such a use is not alternate in the first place.

 If the proposal were with a new option, the user can say 'oh, I
 made a mistake earlier and said that a commit that is not bad as
 'bad'.  Let me replace the commit currently marked as 'bad' with
 this one., I would find it very sensible, actually.

What I find sensible is to not break the semantics of the current
interface.

 I can see that such an operation can be called alternate, but
 --fix might be shorter-and-sweeter-and-to-the-point.

 In the normal case, the commit we offer the user to check (and
 respond with git bisect bad without any commit parameter) is
 always an ancestor of the current 'bad', so the merge-base with
 'bad' and the commit that was just checked would always be the
 current commit.  Using the merge-base thing will be transparent to
 the end users in the normal case, and when the user has off-line
 knowledge that some other commit that is not an ancestor of the
 current 'bad' commit is bad, the merge-base thing will give a better
 behaviour than the current implementation that blindly replaces.

Yes, I agree that it could be an improvement to make it possible for the
user to specify another bad commit. I just think it should be done with
a new option if there is already a bad commit...

 and/or we could make git bisect bad accept any number of bad
 commitishs.

... or by allowing any number of bad commits after git bisect bad.

 Yes, that is exactly what I meant.

 The way I understand the Philip's point is that the user may have
 a-priori knowledge that a breakage from the same cause appears in
 both tips of these branches.  In such a case, we can start bisection
 after marking the merge-base of two 'bad' commits, e.g. 4 in the
 illustration in the message you are responding to, instead of
 including 5, 6, and 8 in the suspect set.

Yeah, I agree that we can do better in this case.

 You need to be careful, though.  An obvious pitfall is what you
 should do when there is a criss-cross 

Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-17 Thread Junio C Hamano
Christian Couder christian.cou...@gmail.com writes:

 On Tue, Mar 17, 2015 at 7:33 PM, Junio C Hamano gits...@pobox.com wrote:
 Christian Couder christian.cou...@gmail.com writes:

 Yes, but the user is supposed to not change the bad pointer for no
 good reason.

 That is irrelevant, no?  Nobody is questioning that the user is
 supposed to judge if a commit is good or bad correctly.

 So if there is already a bad commit and the user gives another
 bad commit, that means that the user knows that it will replace the
 existing bad commit with the new one and that it's done for this
 purpose.

ECANNOTQUITEPARSE.  The user may say git bisect bad $that and we
do not question $that is bad. Git does not know better than the
user.

But that does not mean Git does not know better than the user how
the current bad commit and $that commit are related.  The user is
not interested in replacing at all.  The user is telling just one
single fact, that is, $that is bad.

 I am not quite sure if I am correctly getting what you meant to say,
 but if you meant only when --alternate is given, we should do the
 merge-base thing; we should keep losing the current 'bad' and
 replace it with the new one without the --alternate option, I would
 see that as an exercise of a bad taste.

 What I wanted to say is that if we change git bisect bad commitish,
 so that now it means add a new bad commit instead of the previous
 replace the current bad commit, if any, with this one, then experienced
 users might see that change as a regression in the user interface and
 it might even break scripts.

Huh?  

Step back a bit.  The place you need to start from is to admit the
fact that what git bisect bad committish currently does is
broken.

Try creating this history yourself

a---b---c---d---e---f

and start bisection this way:

$ git bisect start f c
$ git bisect bad a

Immediately after the second command, git bisect moans

Some good revs are not ancestor of the bad rev.
git bisect cannot work properly in this case.
Maybe you mistake good and bad revs?

when it notices that the good rev (i.e. 'c') is no longer an
ancestor of the 'bad', which now points at 'a'.

But that is because git bisect bad _blindly_ moved 'bad' that used
to point at 'f' to 'a', making a good rev (i.e. 'c') an ancestor of
the bad rev, without even bothering to check.

Now, if we fixed this bug and made the bisect_state function more
careful (namely, when accepting bad, make sure it is not beyond
any existing good, or barf like the above, _without_ moving the
bad pointer), the user interface and behaviour would be changed.  Is
that a regression?  No, it is a usability fix and a progress.

Simply put, bisect_state function can become more careful and
intelligent to help users.

I view this user goes out of way to tell us a commit that is known
to be bad as bad, even though it is not what we offered to test and
is not an ancestor of the commit that currently marked as bad case
the same way.  We by now hopefully understand that blindly replacing
the current 'bad' is suboptimal.  By teaching bisect_state to do the
merge-base thing, we would be fixing that.

Why is it a regression?

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-17 Thread Christian Couder
On Mon, Mar 16, 2015 at 10:05 PM, Junio C Hamano gits...@pobox.com wrote:
 Philip Oakley philipoak...@iee.org writes:

 From: Junio C Hamano gits...@pobox.com

 Hence, if you have a history that looks like this:


   G...1---2---3---4---6---8---B
\
 5---7---B

 it follows that 4 must also be bad.  It used to be good long time
 ago somewhere before 1, and somewhere along way on the history,
 there was a single breakage event that we are hunting for.  That
 single event cannot be 5, 6, 7 or 8 because breakage at say 5 would
 not explain why the tip of the upper branch is broken---its breakage
 has no way to propagate there.  The breakage must have happened at 4
 or before that commit.

 Is it not worth at least confirming the assertion that 4 is bad before
 proceding, or at least an option to confirm that in complex scenarios
 where the fault may be devious.

 That raises a somewhat interesting tangent.

 Christian seems to be forever interested in bisect, so I'll add him
 to the Cc list ;-)

 There is no way to give multiple bad from the command line.  You
 can say git bisect start rev rev rev... but that gives only one
 bad and everything else is good.  And once you specify one of the
 above two bad ones (say, the child of 8), then we will not even
 offer the other one (i.e. the child of 7) as a candidate to be
 tested.  So in that sense, confirm that 4 is bad before proceeding
 is a moot point.

 However, you can say git bisect bad rev (and git bisect good
 rev for that matter) on a rev that is unrelated to what the
 current bisection state is.  E.g. after you mark the child of 8 as
 bad, the bisected graph would become

G...1---2---3---4---6---8---B

 and you would be offered to test somewhere in the middle, say, 4.
 But it is perfectly OK for you to respond with git bisect bad 7,
 if you know 7 is bad.

 I _think_ the current code blindly overwrites the bad pointer,
 making the bisection state into this graph if you do so.

G...1---2---3---4
 \
  5---B

Yes, we keep only one bad pointer.

 This is very suboptimal.  The side branch 4-to-7 could be much
 longer than the original trunk 4-to-the-tip, in which case we would
 have made the suspect space _larger_, not smaller.

Yes, but the user is supposed to not change the bad pointer for no
good reason. For example maybe a mistake was made and the first commit
marked as bad was not actually bad.

 We certainly should be able to take advantage of the fact that the
 current bad commit (i.e. the child of 8) and the newly given bad
 commit (i.e. 7) are both known to be bad and mark 4 as bad instead
 when that happens, instead of doing the suboptimal thing the code
 currently does.

Yeah, we could do that, but we would have to allow it only if a
special option is passed on the command line, for example:

git bisect bad --alternate commitish

and/or we could make git bisect bad accept any number of bad commitishs.

That could give additional bonus points to the GSoC student who would
implement it :-)

Thanks,
Christian.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-16 Thread Philip Oakley

From: Junio C Hamano gits...@pobox.com

Kevin Daudt m...@ikke.info writes:


So this ref changes to the bad commit.

For refs/bisect/good-*, I could only find an example snippet:


GOOD=$(git for-each-ref --format=%(objectname) refs/bisect/good-*)


But it's not really clear what * might be expanded to, nor what they
mean. I guess this could use some clarrification in the 
documentation.


Because the history is not linear in Git, bisection works by
shrinking a subgraph of the history DAG that contains yet to be
tested, suspected to have introduced a badness commits.  The
subgraph is defined as anything reachable from _the_ bad commit
(initially, the one you give to the command when you start) that are
not reachable from any of the good commits.

Suppose you started from this graph.  Time flows left to right as
usual.

 ---0---2---4---6---8---9
 \ /
  1---3---5---7

Then mark the initial good and bad commits as G and B.

 ---G---2---4---6---8---B
 \ /
  1---3---5---7

And imagine that you are asked to check 4, which turns out to be
good.  We do not _move_ G to 4; we mark 4 as good, while keeping
0 also as good.

 ---G---2---G---6---8---B
 \ /
  1---3---5---7

And if you are next asked to check 5, and mark it as good, the graph
will become like this:

 ---G---2---G---6---8---B
 \ /
  1---3---G---7

Of course, at this point, the subgraph of suspects are 6, 7, 8 and
9, and the subgraph no longer is affected by the fact that 0 is
good.  But it is crucial to keep 0 marked as good in the step before
this one, before you tested 5, as that is what allows us not having
to test any ancestors of 0 at all.

Now, one may wonder why we need multiple good commits but we do
not need multiple bad commits.  This comes from the nature of
bisection, which is a tool to find a _single_ breakage [*1*], and
a fundamental assumption is that a breakage does not fix itself.

Hence, if you have a history that looks like this:


  G...1---2---3---4---6---8---B
   \
5---7---B

it follows that 4 must also be bad.  It used to be good long time
ago somewhere before 1, and somewhere along way on the history,
there was a single breakage event that we are hunting for.  That
single event cannot be 5, 6, 7 or 8 because breakage at say 5 would
not explain why the tip of the upper branch is broken---its breakage
has no way to propagate there.  The breakage must have happened at 4
or before that commit.


Is it not worth at least confirming the assertion that 4 is bad before
proceding, or at least an option to confirm that in complex scenarios
where the fault may be devious.
[the explicit explanation has been useful for me...]



Which means that if you marked the child of 8 (the tip of the upper
branch) as bad, there is no reason for us to even look at the lower
branch.  As soon as you mark the tip of the upper branch bad, the
bisection can become

  G...1---2---3---4---6---8---B

and without looking at the lower branch, it can find the single
breakage.


[Footnote]

*1* You may be hunting for a single _fix_, and flipping the meaning
   of good and bad, say It used to be broken but somewhere we
   seem to have fixed that bug.  Where did we do that?, marking
   the ones that still has the bug good and the ones that no
   longer has the bug bad.  In that context, you would be looking
   for a single fix.  A more neutral term might be

   - we look for a single event that changes some state.

   - old state before that single event is spelled G O O D, but it
 is pronounced not yet.

   - new state before that single event is spelled B A D, but it is
 pronounced already.
--



--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-16 Thread Kevin Daudt
On Wed, Mar 11, 2015 at 01:13:48PM -0700, Junio C Hamano wrote:
 Kevin Daudt m...@ikke.info writes:
 
  On Tue, Mar 10, 2015 at 04:12:18PM -0700, Junio C Hamano wrote:
 
 
 Step back and think why git bisect --first-parent is sometimes
 desired in the first place.
 
 It is because in the regular bisection, you will almost always end
 up on a commit that is _not_ on the first-parent chain and asked to
 check that commit at a random place on a side branch in the first
 place. And you mark such a commit as bad.
 
 The thing is, traversing from that bad commit that is almost
 always is on a side branch, following the first-parent chain, will
 not be a useful history that leaves out any merged in branches.
 
 When git bisect --first-parent feature gets implemented, do not
 use --first-parent with --bisect limitation has to be lifted
 anyway, but until then, not allowing --first-parent --bisect for
 rev-list but allowing it for log does not buy our users much.
 The output does not give us a nice show me which merges on the
 trunk may have caused the breakage to be examined with the remainder
 of this bisect session.
 
 So, yes, there is a use case for log --bisect --first-parent, once
 there is a working bisect --first-parent, but not until then, the
 command is not useful, I would think.

Thank you for you explanation. My confusion came from incorrectly
assuming refs/bisect/bad and refs/bisect/good-* were pointing to the
initially specified good and bad commits, in which case the combination
does make sense.

I was looking in the manpages for the meaning of the bisect refs, but
could only find something about refs/bisect/bad:

git-bisect(1):
 Eventually there will be no more revisions left to bisect, and you
 will have been left with the first bad kernel revision in
 refs/bisect/bad

So this ref changes to the bad commit.

For refs/bisect/good-*, I could only find an example snippet:

 GOOD=$(git for-each-ref --format=%(objectname) refs/bisect/good-*)

But it's not really clear what * might be expanded to, nor what they
mean. I guess this could use some clarrification in the documentation.

Knowing this, I agree that the combination log --bisect --first-parent
doesn't make sense either.

I will send in a new patch.

Kevin
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-16 Thread Junio C Hamano
Philip Oakley philipoak...@iee.org writes:

 From: Junio C Hamano gits...@pobox.com

 Hence, if you have a history that looks like this:


   G...1---2---3---4---6---8---B
\
 5---7---B

 it follows that 4 must also be bad.  It used to be good long time
 ago somewhere before 1, and somewhere along way on the history,
 there was a single breakage event that we are hunting for.  That
 single event cannot be 5, 6, 7 or 8 because breakage at say 5 would
 not explain why the tip of the upper branch is broken---its breakage
 has no way to propagate there.  The breakage must have happened at 4
 or before that commit.

 Is it not worth at least confirming the assertion that 4 is bad before
 proceding, or at least an option to confirm that in complex scenarios
 where the fault may be devious.

That raises a somewhat interesting tangent.

Christian seems to be forever interested in bisect, so I'll add him
to the Cc list ;-)

There is no way to give multiple bad from the command line.  You
can say git bisect start rev rev rev... but that gives only one
bad and everything else is good.  And once you specify one of the
above two bad ones (say, the child of 8), then we will not even
offer the other one (i.e. the child of 7) as a candidate to be
tested.  So in that sense, confirm that 4 is bad before proceeding
is a moot point.

However, you can say git bisect bad rev (and git bisect good
rev for that matter) on a rev that is unrelated to what the
current bisection state is.  E.g. after you mark the child of 8 as
bad, the bisected graph would become

   G...1---2---3---4---6---8---B

and you would be offered to test somewhere in the middle, say, 4.
But it is perfectly OK for you to respond with git bisect bad 7,
if you know 7 is bad.

I _think_ the current code blindly overwrites the bad pointer,
making the bisection state into this graph if you do so.

   G...1---2---3---4
\
 5---B

This is very suboptimal.  The side branch 4-to-7 could be much
longer than the original trunk 4-to-the-tip, in which case we would
have made the suspect space _larger_, not smaller.

We certainly should be able to take advantage of the fact that the
current bad commit (i.e. the child of 8) and the newly given bad
commit (i.e. 7) are both known to be bad and mark 4 as bad instead
when that happens, instead of doing the suboptimal thing the code
currently does.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-16 Thread Junio C Hamano
Kevin Daudt m...@ikke.info writes:

 So this ref changes to the bad commit.

 For refs/bisect/good-*, I could only find an example snippet:

 GOOD=$(git for-each-ref --format=%(objectname) refs/bisect/good-*)

 But it's not really clear what * might be expanded to, nor what they
 mean. I guess this could use some clarrification in the documentation.

Because the history is not linear in Git, bisection works by
shrinking a subgraph of the history DAG that contains yet to be
tested, suspected to have introduced a badness commits.  The
subgraph is defined as anything reachable from _the_ bad commit
(initially, the one you give to the command when you start) that are
not reachable from any of the good commits.

Suppose you started from this graph.  Time flows left to right as
usual.

  ---0---2---4---6---8---9
  \ /
   1---3---5---7

Then mark the initial good and bad commits as G and B.

  ---G---2---4---6---8---B
  \ /
   1---3---5---7

And imagine that you are asked to check 4, which turns out to be
good.  We do not _move_ G to 4; we mark 4 as good, while keeping
0 also as good.

  ---G---2---G---6---8---B
  \ /
   1---3---5---7

And if you are next asked to check 5, and mark it as good, the graph
will become like this:

  ---G---2---G---6---8---B
  \ /
   1---3---G---7

Of course, at this point, the subgraph of suspects are 6, 7, 8 and
9, and the subgraph no longer is affected by the fact that 0 is
good.  But it is crucial to keep 0 marked as good in the step before
this one, before you tested 5, as that is what allows us not having
to test any ancestors of 0 at all.

Now, one may wonder why we need multiple good commits but we do
not need multiple bad commits.  This comes from the nature of
bisection, which is a tool to find a _single_ breakage [*1*], and
a fundamental assumption is that a breakage does not fix itself.

Hence, if you have a history that looks like this:


   G...1---2---3---4---6---8---B
\
 5---7---B

it follows that 4 must also be bad.  It used to be good long time
ago somewhere before 1, and somewhere along way on the history,
there was a single breakage event that we are hunting for.  That
single event cannot be 5, 6, 7 or 8 because breakage at say 5 would
not explain why the tip of the upper branch is broken---its breakage
has no way to propagate there.  The breakage must have happened at 4
or before that commit.

Which means that if you marked the child of 8 (the tip of the upper
branch) as bad, there is no reason for us to even look at the lower
branch.  As soon as you mark the tip of the upper branch bad, the
bisection can become

   G...1---2---3---4---6---8---B

and without looking at the lower branch, it can find the single
breakage.


[Footnote]

*1* You may be hunting for a single _fix_, and flipping the meaning
of good and bad, say It used to be broken but somewhere we
seem to have fixed that bug.  Where did we do that?, marking
the ones that still has the bug good and the ones that no
longer has the bug bad.  In that context, you would be looking
for a single fix.  A more neutral term might be

- we look for a single event that changes some state.

- old state before that single event is spelled G O O D, but it
  is pronounced not yet.

- new state before that single event is spelled B A D, but it is
  pronounced already.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-11 Thread Junio C Hamano
Kevin Daudt m...@ikke.info writes:

 On Tue, Mar 10, 2015 at 04:12:18PM -0700, Junio C Hamano wrote:

 What does such a command line _mean_?  It tells us this:
 
 Define a set by having the bad ref as a positive end, and
 having all the good refs as negative (uninteresting) boundary.
 
 That is a way to show commits that are reachable from the bad one
 and excluding the ones that are reachable from any of the known-good
 commits.  The area of the graph in the current bisection that
 contains suspect commits.
 
 Now, what does it mean to pull only the first-parent chain starting
 from the bad one in such a set in the first place?  What does the
 resulting set of commits mean?

 In that case it will leave out any merged in branches.

Needs a bit more thinking (hint: branches merged into *what*?).

 I recalled reading something about this. Searching found me the GSoC
 idea:

 When your project is strictly new features are merged into trunk,
 never the other way around, it is handy to be able to first find a
 merge on the trunk that merged a topic to point fingers at when a
 bug appears, instead of having to drill down to the individual
 commit on the faulty side branch.

 So there is definitely a use case for --bisect --first-parent, which
 would show you those commits that would be part of the bisection.

Step back and think why git bisect --first-parent is sometimes
desired in the first place.

It is because in the regular bisection, you will almost always end
up on a commit that is _not_ on the first-parent chain and asked to
check that commit at a random place on a side branch in the first
place. And you mark such a commit as bad.

The thing is, traversing from that bad commit that is almost
always is on a side branch, following the first-parent chain, will
not be a useful history that leaves out any merged in branches.

When git bisect --first-parent feature gets implemented, do not
use --first-parent with --bisect limitation has to be lifted
anyway, but until then, not allowing --first-parent --bisect for
rev-list but allowing it for log does not buy our users much.
The output does not give us a nice show me which merges on the
trunk may have caused the breakage to be examined with the remainder
of this bisect session.

So, yes, there is a use case for log --bisect --first-parent, once
there is a working bisect --first-parent, but not until then, the
command is not useful, I would think.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-11 Thread Kevin Daudt
On Tue, Mar 10, 2015 at 04:12:18PM -0700, Junio C Hamano wrote:
 Kevin Daudt m...@ikke.info writes:
 
  git log --bisect seems to do something different then git rev-list
  --bisect
 
  From git-log(1):
 
  Pretend as if the bad bisection ref refs/bisect/bad was listed and
  as if it was followed by --not and the good bisection refs
  refs/bisect/good-* on the command line.
 
  This seems to just add addition refs to the log command, which seems
  unrelated to what rev-list --bisect does.
 
  So I don't see why git log --bisect --first-parent should be prohibited
  (unless this combination doesn't make sense on itself).
 
 Well, but think if your unless holds true or not yourself first
 and then say I do not think this combination doesn't make sense,
 if you truly mean I don't see why ... should be prohibited.
 
 What does such a command line _mean_?  It tells us this:
 
 Define a set by having the bad ref as a positive end, and
 having all the good refs as negative (uninteresting) boundary.
 
 That is a way to show commits that are reachable from the bad one
 and excluding the ones that are reachable from any of the known-good
 commits.  The area of the graph in the current bisection that
 contains suspect commits.
 
 Now, what does it mean to pull only the first-parent chain starting
 from the bad one in such a set in the first place?  What does the
 resulting set of commits mean?
 
 

In that case it will leave out any merged in branches.

I recalled reading something about this. Searching found me the GSoC
idea:

When your project is strictly new features are merged into trunk,
never the other way around, it is handy to be able to first find a
merge on the trunk that merged a topic to point fingers at when a
bug appears, instead of having to drill down to the individual
commit on the faulty side branch.

So there is definitely a use case for --bisect --first-parent, which
would show you those commits that would be part of the bisection.


--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-10 Thread Junio C Hamano
Kevin Daudt m...@ikke.info writes:

 rev-list --bisect is used by git bisect, but never together with
 --first-parent. Because rev-list --bisect together with --first-parent
 is not handled currently, and even leads to segfaults, refuse to use
 both options together.

 Suggested-by: Junio C. Hamano gits...@pobox.com
 Helped-by: Eric Sunshine sunsh...@sunshineco.com
 Signed-off-by: Kevin Daudt m...@ikke.info
 ---
 Changes since v3:

 * Added an ifdef::git-rev-list[] guard around the warning in the
   --first-parent section so that it only shows up in `man git-rev-list`
   and not in `man git log`

 * Added the warning also to the --bisect section.

I wonder what git log --first-parent --bisect A..B should do,
though.

Wouldn't the rejection belong to revision.c::setup_revisions(),
where we reject combined use of (--reverse, --walk-reflogs) and
(--children, --parents), to apply this to all commands in the log
family that uses the revision walker machinery?


  Documentation/rev-list-options.txt | 4 
  builtin/rev-list.c | 3 +++
  t/t6000-rev-list-misc.sh   | 4 
  3 files changed, 11 insertions(+)

 diff --git a/Documentation/rev-list-options.txt 
 b/Documentation/rev-list-options.txt
 index 4ed8587..a148672 100644
 --- a/Documentation/rev-list-options.txt
 +++ b/Documentation/rev-list-options.txt
 @@ -124,6 +124,9 @@ parents) and `--max-parents=-1` (negative numbers denote 
 no upper limit).
   adjusting to updated upstream from time to time, and
   this option allows you to ignore the individual commits
   brought in to your history by such a merge.
 +ifdef::git-rev-list[]
 + Cannot be combined with --bisect.
 +endif::git-rev-list[]
  
  --not::
   Reverses the meaning of the '{caret}' prefix (or lack thereof)
 @@ -567,6 +570,7 @@ would be of roughly the same length.  Finding the change 
 which
  introduces a regression is thus reduced to a binary search: repeatedly
  generate and test new 'midpoint's until the commit chain is of length
  one.
 +Cannot be combined with --first-parent.
  
  --bisect-vars::
   This calculates the same as `--bisect`, except that refs in
 diff --git a/builtin/rev-list.c b/builtin/rev-list.c
 index ff84a82..f5da2a4 100644
 --- a/builtin/rev-list.c
 +++ b/builtin/rev-list.c
 @@ -291,6 +291,9 @@ int cmd_rev_list(int argc, const char **argv, const char 
 *prefix)
   if (revs.bisect)
   bisect_list = 1;
  
 + if (revs.first_parent_only  revs.bisect)
 + die(_(--first-parent is incompattible with --bisect));
 +
   if (DIFF_OPT_TST(revs.diffopt, QUICK))
   info.flags |= REV_LIST_QUIET;
   for (i = 1 ; i  argc; i++) {
 diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
 index 2602086..1f58b46 100755
 --- a/t/t6000-rev-list-misc.sh
 +++ b/t/t6000-rev-list-misc.sh
 @@ -96,4 +96,8 @@ test_expect_success 'rev-list can show index objects' '
   test_cmp expect actual
  '
  
 +test_expect_success '--bisect and --first-parent can not be combined' '
 + test_must_fail git rev-list --bisect --first-parent HEAD
 +'
 +
  test_done
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-10 Thread Kevin Daudt
On Tue, Mar 10, 2015 at 03:09:54PM -0700, Junio C Hamano wrote:
 Kevin Daudt m...@ikke.info writes:
 
  rev-list --bisect is used by git bisect, but never together with
  --first-parent. Because rev-list --bisect together with --first-parent
  is not handled currently, and even leads to segfaults, refuse to use
  both options together.
 
  Suggested-by: Junio C. Hamano gits...@pobox.com
  Helped-by: Eric Sunshine sunsh...@sunshineco.com
  Signed-off-by: Kevin Daudt m...@ikke.info
  ---
  Changes since v3:
 
  * Added an ifdef::git-rev-list[] guard around the warning in the
--first-parent section so that it only shows up in `man git-rev-list`
and not in `man git log`
 
  * Added the warning also to the --bisect section.
 
 I wonder what git log --first-parent --bisect A..B should do,
 though.
 
 Wouldn't the rejection belong to revision.c::setup_revisions(),
 where we reject combined use of (--reverse, --walk-reflogs) and
 (--children, --parents), to apply this to all commands in the log
 family that uses the revision walker machinery?
 

git log --bisect seems to do something different then git rev-list
--bisect

From git-log(1):

Pretend as if the bad bisection ref refs/bisect/bad was listed and
as if it was followed by --not and the good bisection refs
refs/bisect/good-* on the command line.

This seems to just add addition refs to the log command, which seems
unrelated to what rev-list --bisect does.

So I don't see why git log --bisect --first-parent should be prohibited
(unless this combination doesn't make sense on itself).

Kevin.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-10 Thread Junio C Hamano
Kevin Daudt m...@ikke.info writes:

 git log --bisect seems to do something different then git rev-list
 --bisect

 From git-log(1):

 Pretend as if the bad bisection ref refs/bisect/bad was listed and
 as if it was followed by --not and the good bisection refs
 refs/bisect/good-* on the command line.

 This seems to just add addition refs to the log command, which seems
 unrelated to what rev-list --bisect does.

 So I don't see why git log --bisect --first-parent should be prohibited
 (unless this combination doesn't make sense on itself).

Well, but think if your unless holds true or not yourself first
and then say I do not think this combination doesn't make sense,
if you truly mean I don't see why ... should be prohibited.

What does such a command line _mean_?  It tells us this:

Define a set by having the bad ref as a positive end, and
having all the good refs as negative (uninteresting) boundary.

That is a way to show commits that are reachable from the bad one
and excluding the ones that are reachable from any of the known-good
commits.  The area of the graph in the current bisection that
contains suspect commits.

Now, what does it mean to pull only the first-parent chain starting
from the bad one in such a set in the first place?  What does the
resulting set of commits mean?


--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4] rev-list: refuse --first-parent combined with --bisect

2015-03-09 Thread Kevin Daudt
rev-list --bisect is used by git bisect, but never together with
--first-parent. Because rev-list --bisect together with --first-parent
is not handled currently, and even leads to segfaults, refuse to use
both options together.

Suggested-by: Junio C. Hamano gits...@pobox.com
Helped-by: Eric Sunshine sunsh...@sunshineco.com
Signed-off-by: Kevin Daudt m...@ikke.info
---
Changes since v3:

* Added an ifdef::git-rev-list[] guard around the warning in the
  --first-parent section so that it only shows up in `man git-rev-list`
  and not in `man git log`

* Added the warning also to the --bisect section.

 Documentation/rev-list-options.txt | 4 
 builtin/rev-list.c | 3 +++
 t/t6000-rev-list-misc.sh   | 4 
 3 files changed, 11 insertions(+)

diff --git a/Documentation/rev-list-options.txt 
b/Documentation/rev-list-options.txt
index 4ed8587..a148672 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -124,6 +124,9 @@ parents) and `--max-parents=-1` (negative numbers denote no 
upper limit).
adjusting to updated upstream from time to time, and
this option allows you to ignore the individual commits
brought in to your history by such a merge.
+ifdef::git-rev-list[]
+   Cannot be combined with --bisect.
+endif::git-rev-list[]
 
 --not::
Reverses the meaning of the '{caret}' prefix (or lack thereof)
@@ -567,6 +570,7 @@ would be of roughly the same length.  Finding the change 
which
 introduces a regression is thus reduced to a binary search: repeatedly
 generate and test new 'midpoint's until the commit chain is of length
 one.
+Cannot be combined with --first-parent.
 
 --bisect-vars::
This calculates the same as `--bisect`, except that refs in
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index ff84a82..f5da2a4 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -291,6 +291,9 @@ int cmd_rev_list(int argc, const char **argv, const char 
*prefix)
if (revs.bisect)
bisect_list = 1;
 
+   if (revs.first_parent_only  revs.bisect)
+   die(_(--first-parent is incompattible with --bisect));
+
if (DIFF_OPT_TST(revs.diffopt, QUICK))
info.flags |= REV_LIST_QUIET;
for (i = 1 ; i  argc; i++) {
diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
index 2602086..1f58b46 100755
--- a/t/t6000-rev-list-misc.sh
+++ b/t/t6000-rev-list-misc.sh
@@ -96,4 +96,8 @@ test_expect_success 'rev-list can show index objects' '
test_cmp expect actual
 '
 
+test_expect_success '--bisect and --first-parent can not be combined' '
+   test_must_fail git rev-list --bisect --first-parent HEAD
+'
+
 test_done
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html