Re: [RFC 0/9] bisect: allow git bisect to be used with repos containing damaged trees.
- From
Jon Seymour <jon.seymour@gmail.com>
- Date
- Jul 25, 2011, 09:28 UTC
- Message-ID
- <CAH3AnrrVwodvtwWfaJCJqjuHThtv75jaWeDjvwRgdFbgXA3ziA@mail.gmail.com>
- In-Reply-To
- <7v1uxfwmq3.fsf@alter.siamese.dyndns.org>
On Mon, Jul 25, 2011 at 4:35 AM, Junio C Hamano <gitster@pobox.com> wrote:
Show 7 quoted lines
> Jon Seymour <jon.seymour@gmail.com> writes: > >> ... In particular, it >> allows git bisect to be used to locate commits containing damaged trees. > > I am afraid it wouldn't allow it, and I am not going to take this series > that adds an option to bisect to ignore errors during checkout.
Understand that you don't wish to accept the series, but I do think you are mistaken about whether it will work.
Show 13 quoted lines
> > Remember that bisection is to find a single event in the history whose > effect consistently persists in all the commits into the future from that > point. For example, if you have this history: > > ---A---B---C > > and there is a bitflip in a blob contained in the commit B's tree, you may > not be able to check it out. But that does _not_ mean you cannot check C > out due to a corrupt object in B. The change going from B to C may be to > remove that blob, for example. "A tree that refers to a corrupt object was > introduced by this commit" is not a single event whose effect cascades > through the history into the future [*1*].
I don't think you understood my intention. Suppose, I have
B4 - B5 - B6' - B7' - B8' - B9
such that B6 and B7 and B8 all contain a damaged tree, but B4, B5 and B9 don't since it contains a different tree, then:
git bisect start B8' B4 --ignore-checkout-failure && git bisect run eval "git status >/dev/null 2>&1 || false"
will stop with bisect/bad = B6'
This is exactly the result I wanted, and I discover B6' with a binary search, rather than a linear search.
(I could also discover B8' with a binary search by reversing the sense of the test).
In other words, I don't understand why you say that it won't work - since it clearly does work for the purposes which I intended.
For a real example, see [1].
> > Besides, if you have a corrupt commit, your history traversal may not even > be correct, as we won't be reading its parent pointers correctly. >
Agreed. This only works when you have dealt with broken commits by applying suitable grafts.
I noticed a neat heuristic for doing this is to compute the diff between the first good commit after the broken region and the first good dangling commit (as reported by fsck) - the one with the smallest delta may well be a suitable object to use as one end of the graft. [ needs to be sanity checked, of course ]. It may not be perfect, but when the objective is to get a consistent (in the sense of fsck), if incomplete repository, it may well do.
Show 7 quoted lines
> Having said that, an option to bisect that does _not_ touch the index nor > the working tree at all may be a useful thing to have. The test you want > to run on the candidate revisions bisect suggests may not need a working > tree (e.g. it may be built around "git grep -e foo $revision -- $path"), > and it may work just as well for the bisection you wanted to do in your > broken repository. >
I am happy to do this, since clearly enables a superset of the cases handled by --ignore-checkout-failure.
I propose to do this with a new ref (perhaps BISECT_CURSOR) which will be used in place of HEAD for the purposes of driving the bisection algorithm if --no-checkout has been specified on the git bisect start command.
Any comments?
jon.
---------------- [1] a test execution that shows that the bisection does, in fact, help to identify the boundaries of a broken region.
(Note NEAREST could also be discovered with a binary search, but this isn't done in this example).
expecting success:
git bisect reset &&
NEAREST=$(git rev-list broken | while read c
do
git ls-tree -r $c >/dev/null || {
echo $c;
exit 0;
}
done) &&
git bisect start $NEAREST $HASH1 --ignore-checkout-failure &&
git bisect run eval "git status >/dev/null 2>&1 || false" >
my_bisect_log.txt &&
grep "$BROKEN_HASH6 is the first bad commit" my_bisect_log.txtWe are not bisecting. error: Could not read 39f7e61a724187ab767d2e08442d9b6b9dab587d Bisecting: 3 revisions left to test after this (roughly 2 steps) fatal: unable to read tree 39f7e61a724187ab767d2e08442d9b6b9dab587d warn: checkout failed. Updating HEAD directly. The working tree and index may be inconsistent. [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>. fatal: unable to read tree 39f7e61a724187ab767d2e08442d9b6b9dab587d warn: checkout failed. Updating HEAD directly. The working tree and index may be inconsistent. fatal: unable to read tree 39f7e61a724187ab767d2e08442d9b6b9dab587d warn: checkout failed. Updating HEAD directly. The working tree and index may be inconsistent. 1b0312df05d867dc49f5d9f82617ee42cce1430d is the first bad commit ok 49 - bisect: find the first inconsistent commit