Subject: Re: [PATCH 1/9 v4] bisect: add "git bisect replace" subcommand

From: Junio C Hamano <[email-masked]>
Date: Tue, 11 Nov 2008 15:23:27 -0800

Christian Couder <[email-masked]> writes:

> This subcommand should be used when you have a branch or a part of a
> branch that isn't easily bisectable because of a bug that has been
> fixed latter.

While I acknowledge your effort to make bisect easier to use, I do
not think this is going in the right direction, from the point of view of
the workflow.

I do agree that the issue it tries to solve is a problem in real life.
When you want to hunt for a bug, it is certainly possible that your tests
fail for a bug that is unrelated to what you are hunting for for a range
of commits.  Borrowing from your picture:

    ...--O--A--X1--X2--...--Xn--B--...

non of the commit marked as Xi may not be testable.

But at that point, will you really spend time to rebuild history between A
and B by fixing an unrelated bug that hinders your bisect, so that you can
have a parallel history that is bisectable?  I doubt anybody would.

Even if we assume that somebody wants to adopt the workflow to first fix
an unrelated bug (that may be totally uninteresting for the purpose of
solving the original issue he set out to figure out) to rewrite the
history, what he first needs to do is to find out what part of the history
to rewrite.  IOW, he needs to know A and B (and in general, the history is
not even linear).  Maybe he guesses what A and B is.  But for one thing,
after making the guess, he would certainly test A and B to see if the
original issue exists at these commits.  The sequence of commits Xi become
irrelevant if A turns out to be bad or B turns out to be good.

And if A is good and B is bad, then the _original bug_ is in the very
sequence of Xi you are going to rewrite.  By the time you made a rewritten
history with sequence of commits Yi to be grafted like this:

         C--Y1--Y2--...--Yn
       /
 ...--O--A--X1--X2--...--Xn--B--...

to make it bisectable, it is very likely that you would have already seen
the original bug.

In such a case where you need to figure out what an unrelated bug is, and
which commit A and B are involved while bisecting, I think you are much
better off using bisect skip, as Johannes mentioned earlier.

On the other hand, if you already have a well-known bug that was
introduced at A whose fix at B is also very well-known, you would not even
need a separate "bisect replace" command nor replace_parents() machinery
only for the purpose of bisection, would you?  In such a case I think you
can just use a usual graft.

I have a separate idea make 'grafts' easier on object transfer, that is
somewhat related to this one, by the way.  Instead of making the grafts
completely a local matter as we do now, we can reserve refs/replace/
namespace, and record a new commit object to replace an existing commit
whose object name is $sha1 as refs/replace/$sha1.  We make almost all the
commands except object enumeration (fsck, receive-pack, send-pack, prune,
etc.  Roughly speaking, anything that involves "rev-list --objects") honor
this commit replacement, so that any time you ask for commit $sha1, the
object layer gives you the replacement commit object back.  In this way,
you can clone or fetch from such a repository (along with refs in
refs/replace/ hierarchy) and fsck/prune won't lose the original parents
(because it does not see replacements).  Things like paranoid update hook
needs to become very careful about refs/replace/ for security reasons, but
I think this would make the grafts much easier to use.