This commits adds a discussion of the challenge of bisecting
merge commits to the user manual. The text is slightly
adapted from a mail by Junio C Hamano [off-list ref]
to the mailing list
<http://marc.info/?l=git&m=119403257315527&w=2>.
The discussion is added to "Exploring git history" in a
sub-section titled "Advanced topics". The discussion requires
detailed knowledge about git. It is assumed that the reader will
skip advanced topics on first reading. At least the text suggest
to do so.
Signed-off-by: Steffen Prohaska <redacted>
---
Documentation/user-manual.txt | 89 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 89 insertions(+), 0 deletions(-)
Junio's discussion was enlightening for me. I think it's a good idea to add
such discussions to the user manual. It was not obvious to me where to place
the discussion in the current structure of the manual. So I added "Advanced
topics".
Is a sub-section "Advanced topics" a good idea? Any better suggestions?
Steffen
@@ -934,6 +934,95 @@ Figuring out why this works is left as an exercise to the (advanced) student. The gitlink:git-log[1], gitlink:git-diff-tree[1], and gitlink:git-hash-object[1] man pages may prove helpful.+[[history-advanced-topics]]+Advanced topics+---------------+This section covers advanced topics that typically require more+knowledge about git than the manual presented to this point.++You may want to skip the section at first reading, and come back+later when you have a better understanding of git.++[[bisect-merges]]+Why bisecting merge commits can be harder than bisecting linear history+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The following text is based upon an email by Junio C. Hamano to+the git mailing list+(link:http://marc.info/?l=git&m=119403257315527&w=2[link:http://marc.info/?l=git&m=119403257315527&w=2]).+It was slightly adapted for this manual.++Bisecting merges can be challenging due to the complexity of+changes introduced at a merge. Bisecting through merges is not a+technical problem. The real problem is what to do when the+culprit turns out to be a merge commit. How to spot what really+is wrong, and figure out how to fix. The problem is not for the+tool but for the human, and it is real.++Imagine this history.++................................................+ ---Z---o---X---...---o---A---C---D+ \ /+ o---o---Y---...---o---B+................................................++Suppose that on the upper development line, the meaning of one+of the functions existed at Z was changed at commit X. The+commits from Z leading to A change both the function's+implementation and all calling sites that existed at Z, as well+as new calling sites they add, to be consistent. There is no+bug at A.++Suppose in the meantime the lower development line somebody+added a new calling site for that function at commit Y. The+commits from Z leading to B all assume the old semantics of that+function and the callers and the callee are consistent with each+other. There is no bug at B, either.++You merge to create C. There is no textual conflict with this+three way merge, and the result merges cleanly. You bisect+this, because you found D is bad and you know Z was good. Your+bisect will find that C (merge) is broken. Understandably so,+as at C, the new calling site of the function added by the lower+branch is not converted to the new semantics, while all the+other calling sites that already existed at Z would have been+converted by the merge. The new calling site has semantic+adjustment needed, but you do not know that yet. You need to+find out that is the cause of the breakage by looking at the+merge commit C and the history leading to it.++How would you do that?++Both "git diff A C" and "git diff B C" would be an enormous patch.+Each of them essentially shows the whole change on each branch+since they diverged. The developers may have well behaved to+create good commits that follow the "commit small, commit often,+commit well contained units" mantra, and each individual commit+leading from Z to A and from Z to B may be easy to review and+understand, but looking at these small and easily reviewable+steps alone would not let you spot the breakage. You need to+have a global picture of what the upper branch did (and+among many, one of them is to change the semantics of that+particular function) and look first at the huge "diff A C"+(which shows the change the lower branch introduces), and see if+that huge change is consistent with what have been done between+Z and A.++If you linearlize the history by rebasing the lower branch on+top of upper, instead of merging, the bug becomes much easier to+find and understand. Your history would instead be:++................................................................+ ---Z---o---X--...---o---A---o---o---Y*--...---o---B*--D*+................................................................++and there is a single commit Y* between A and B* that introduced+the new calling site that still uses the old semantics of the+function, even though that was already modified at X. "git show+Y*" will be a much smaller patch than "git diff A C" and it is+much easier to deal with.++ [[Developing-with-git]] Developing with git ===================
Hello Steffen,
A couple of language nits:
* Steffen Prohaska wrote on Sun, Nov 04, 2007 at 10:16:13AM CET:
+Suppose that on the upper development line, the meaning of one
+of the functions existed at Z was changed at commit X. The
s/functions/& that/
+commits from Z leading to A change both the function's
+implementation and all calling sites that existed at Z, as well
+as new calling sites they add, to be consistent. There is no
+bug at A.
[...]
+You merge to create C. There is no textual conflict with this
+three way merge, and the result merges cleanly. You bisect
+this, because you found D is bad and you know Z was good. Your
+bisect will find that C (merge) is broken. Understandably so,
+as at C, the new calling site of the function added by the lower
+branch is not converted to the new semantics, while all the
+other calling sites that already existed at Z would have been
+converted by the merge. The new calling site has semantic
+adjustment needed, but you do not know that yet. You need to
+find out that is the cause of the breakage by looking at the
s/that/that that/
+merge commit C and the history leading to it.
[...]
+If you linearlize the history by rebasing the lower branch on
+top of upper, instead of merging, the bug becomes much easier to
s/upper/the &/
+find and understand. Your history would instead be:
@@ -934,6 +934,95 @@ Figuring out why this works is left as an
exercise to the (advanced)
[...]
+
+Imagine this history.
+
+................................................
+ ---Z---o---X---...---o---A---C---D
+ \ /
+ o---o---Y---...---o---B
+................................................
+
I don't know how you chose these letters, but I don't find them
particularly intuitive to remember.
................................................
---B---o---X---...---o---Y---M---H
\ /
o---o---T---...---o---Z
................................................
would be better (IMO): B stands for "Branch point"
M stands for "Merge"
H stands for "HEAD"
T stands for "Topic"
Otherwise thanks for documenting this, the patch looks fine to me.
--
Benoit Sigoure aka Tsuna
EPITA Research and Development Laboratory
This commits adds a discussion of the challenge of bisecting
merge commits to the user manual. The text is slightly
adapted from a mail by Junio C Hamano [off-list ref]
to the mailing list
<http://marc.info/?l=git&m=119403257315527&w=2>.
The discussion is added to "Exploring git history" in a
sub-section titled "Advanced topics". The discussion requires
detailed knowledge about git. It is assumed that the reader will
skip advanced topics on first reading. At least the text suggest
to do so.
Signed-off-by: Steffen Prohaska <redacted>
---
Documentation/user-manual.txt | 89 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 89 insertions(+), 0 deletions(-)
Some minor errors were fixed. Thanks to [off-list ref].
I kept the naming of the commits. Benoit Sigoure suggested to choose
a different naming which he claims would be easier to remember.
I'm not convinced. The current naming starts with X, Y, Z on the left
and names the remaining commits on the right with A, B, C, D. This
is simple and give sufficient orientation.
Steffen
@@ -934,6 +934,95 @@ Figuring out why this works is left as an exercise to the (advanced) student. The gitlink:git-log[1], gitlink:git-diff-tree[1], and gitlink:git-hash-object[1] man pages may prove helpful.+[[history-advanced-topics]]+Advanced topics+---------------+This section covers advanced topics that typically require more+knowledge about git than the manual presented to this point.++You may want to skip the section at first reading, and come back+later when you have a better understanding of git.++[[bisect-merges]]+Why bisecting merge commits can be harder than bisecting linear history+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The following text is based upon an email by Junio C. Hamano to+the git mailing list+(link:http://marc.info/?l=git&m=119403257315527&w=2[link:http://marc.info/?l=git&m=119403257315527&w=2]).+It was slightly adapted for this manual.++Bisecting merges can be challenging due to the complexity of+changes introduced at a merge. Bisecting through merges is not a+technical problem. The real problem is what to do when the+culprit turns out to be a merge commit. How to spot what really+is wrong, and figure out how to fix. The problem is not for the+tool but for the human, and it is real.++Imagine this history.++................................................+ ---Z---o---X---...---o---A---C---D+ \ /+ o---o---Y---...---o---B+................................................++Suppose that on the upper development line, the meaning of one+of the functions that existed at Z was changed at commit X. The+commits from Z leading to A change both the function's+implementation and all calling sites that existed at Z, as well+as new calling sites they add, to be consistent. There is no+bug at A.++Suppose in the meantime the lower development line somebody+added a new calling site for that function at commit Y. The+commits from Z leading to B all assume the old semantics of that+function and the callers and the callee are consistent with each+other. There is no bug at B, either.++You merge to create C. There is no textual conflict with this+three way merge, and the result merges cleanly. You bisect+this, because you found D is bad and you know Z was good. Your+bisect will find that C (merge) is broken. Understandably so,+as at C, the new calling site of the function added by the lower+branch is not converted to the new semantics, while all the+other calling sites that already existed at Z would have been+converted by the merge. The new calling site has semantic+adjustment needed, but you do not know that yet. You need to+find out that that is the cause of the breakage by looking at the+merge commit C and the history leading to it.++How would you do that?++Both "git diff A C" and "git diff B C" would be an enormous patch.+Each of them essentially shows the whole change on each branch+since they diverged. The developers may have well behaved to+create good commits that follow the "commit small, commit often,+commit well contained units" mantra, and each individual commit+leading from Z to A and from Z to B may be easy to review and+understand, but looking at these small and easily reviewable+steps alone would not let you spot the breakage. You need to+have a global picture of what the upper branch did (and+among many, one of them is to change the semantics of that+particular function) and look first at the huge "diff A C"+(which shows the change the lower branch introduces), and see if+that huge change is consistent with what have been done between+Z and A.++If you linearize the history by rebasing the lower branch on+top of the upper, instead of merging, the bug becomes much easier to+find and understand. Your history would instead be:++................................................................+ ---Z---o---X--...---o---A---o---o---Y*--...---o---B*--D*+................................................................++and there is a single commit Y* between A and B* that introduced+the new calling site that still uses the old semantics of the+function, even though that was already modified at X. "git show+Y*" will be a much smaller patch than "git diff A C" and it is+much easier to deal with.++ [[Developing-with-git]] Developing with git ===================
Hi Steffen,
On Nov 7, 2007, at 10:50 PM, Steffen Prohaska wrote:
This commits adds a discussion of the challenge of bisecting
merge commits to the user manual. The text is slightly
adapted from a mail by Junio C Hamano [off-list ref]
to the mailing list
<http://marc.info/?l=git&m=119403257315527&w=2>.
The discussion is added to "Exploring git history" in a
sub-section titled "Advanced topics". The discussion requires
detailed knowledge about git. It is assumed that the reader will
skip advanced topics on first reading. At least the text suggest
to do so.
Signed-off-by: Steffen Prohaska <redacted>
---
Documentation/user-manual.txt | 89 ++++++++++++++++++++++++++++++
+++++++++++
1 files changed, 89 insertions(+), 0 deletions(-)
Some minor errors were fixed. Thanks to [off-list ref].
I kept the naming of the commits. Benoit Sigoure suggested to choose
a different naming which he claims would be easier to remember.
I'm not convinced. The current naming starts with X, Y, Z on the left
and names the remaining commits on the right with A, B, C, D. This
is simple and give sufficient orientation.
I still disagree but... fair enough ;)
You end up comparing [ABCD] with [XYZ] which (to me) is hard to
follow because it's like you were comparing two different kind of
entities. I tend to think more in term of branch (e.g. what's
happened to the upper branch and what's happened to the lower branch,
rather than think in terms of "before a point in time" and "after
that point in time"). Because of that, I constantly need to look
back at the scheme to find out what is `A', what is `Z' etc.
Some more comments below. Sorry for not spotting these earlier.
@@ -934,6 +934,95 @@ Figuring out why this works is left as an
exercise to the (advanced)
student. The gitlink:git-log[1], gitlink:git-diff-tree[1], and
gitlink:git-hash-object[1] man pages may prove helpful.
+[[history-advanced-topics]]
+Advanced topics
+---------------
+This section covers advanced topics that typically require more
+knowledge about git than the manual presented to this point.
+
+You may want to skip the section at first reading, and come back
I think the correct wording here is "on first reading". If a native
English speaker could confirm this...
+later when you have a better understanding of git.
+
+[[bisect-merges]]
+Why bisecting merge commits can be harder than bisecting linear
history
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~
+The following text is based upon an email by Junio C. Hamano to
+the git mailing list
+(link:http://marc.info/?l=git&m=119403257315527&w=2[link:http://
marc.info/?l=git&m=119403257315527&w=2]).
+It was slightly adapted for this manual.
+
+Bisecting merges can be challenging due to the complexity of
+changes introduced at a merge. Bisecting through merges is not a
s/at a merge/& point/ ?
+technical problem. The real problem is what to do when the
+culprit turns out to be a merge commit. How to spot what really
+is wrong, and figure out how to fix. The problem is not for the
+tool but for the human, and it is real.
+
+Imagine this history.
+
+................................................
+ ---Z---o---X---...---o---A---C---D
+ \ /
+ o---o---Y---...---o---B
+................................................
+
+Suppose that on the upper development line, the meaning of one
+of the functions that existed at Z was changed at commit X. The
+commits from Z leading to A change both the function's
+implementation and all calling sites that existed at Z, as well
+as new calling sites they add, to be consistent. There is no
+bug at A.
+
+Suppose in the meantime the lower development line somebody
s/Suppose/& that/
+added a new calling site for that function at commit Y. The
+commits from Z leading to B all assume the old semantics of that
+function and the callers and the callee are consistent with each
+other. There is no bug at B, either.
+
+You merge to create C. There is no textual conflict with this
+three way merge, and the result merges cleanly. You bisect
+this, because you found D is bad and you know Z was good. Your
+bisect will find that C (merge) is broken. Understandably so,
+as at C, the new calling site of the function added by the lower
+branch is not converted to the new semantics, while all the
+other calling sites that already existed at Z would have been
+converted by the merge. The new calling site has semantic
+adjustment needed, but you do not know that yet. You need to
s/adjustment/&s/
+find out that that is the cause of the breakage by looking at the
+merge commit C and the history leading to it.
+
+How would you do that?
+
+Both "git diff A C" and "git diff B C" would be an enormous patch.
+Each of them essentially shows the whole change on each branch
+since they diverged. The developers may have well behaved to
+create good commits that follow the "commit small, commit often,
+commit well contained units" mantra, and each individual commit
+leading from Z to A and from Z to B may be easy to review and
+understand, but looking at these small and easily reviewable
+steps alone would not let you spot the breakage. You need to
+have a global picture of what the upper branch did (and
+among many, one of them is to change the semantics of that
+particular function) and look first at the huge "diff A C"
+(which shows the change the lower branch introduces), and see if
+that huge change is consistent with what have been done between
+Z and A.
+
+If you linearize the history by rebasing the lower branch on
+top of the upper, instead of merging, the bug becomes much easier to
+find and understand. Your history would instead be:
+
+................................................................
+ ---Z---o---X--...---o---A---o---o---Y*--...---o---B*--D*
+................................................................
+
+and there is a single commit Y* between A and B* that introduced
+the new calling site that still uses the old semantics of the
+function, even though that was already modified at X. "git show
+Y*" will be a much smaller patch than "git diff A C" and it is
+much easier to deal with.
+
+
[[Developing-with-git]]
Developing with git
===================
Thank you!
--
Benoit Sigoure aka Tsuna
EPITA Research and Development Laboratory
From: J. Bruce Fields <hidden> Date: 2016-06-15 22:43:48
On Wed, Nov 07, 2007 at 11:16:06PM +0100, Benoit Sigoure wrote:
Hi Steffen,
On Nov 7, 2007, at 10:50 PM, Steffen Prohaska wrote:
quoted
This commits adds a discussion of the challenge of bisecting
merge commits to the user manual. The text is slightly
adapted from a mail by Junio C Hamano [off-list ref]
to the mailing list
<http://marc.info/?l=git&m=119403257315527&w=2>.
The discussion is added to "Exploring git history" in a
sub-section titled "Advanced topics". The discussion requires
detailed knowledge about git. It is assumed that the reader will
skip advanced topics on first reading. At least the text suggest
to do so.
Signed-off-by: Steffen Prohaska <redacted>
---
Documentation/user-manual.txt | 89
+++++++++++++++++++++++++++++++++++++++++
1 files changed, 89 insertions(+), 0 deletions(-)
Some minor errors were fixed. Thanks to [off-list ref].
I kept the naming of the commits. Benoit Sigoure suggested to choose
a different naming which he claims would be easier to remember.
I'm not convinced. The current naming starts with X, Y, Z on the left
and names the remaining commits on the right with A, B, C, D. This
is simple and give sufficient orientation.
I still disagree but... fair enough ;)
You end up comparing [ABCD] with [XYZ] which (to me) is hard to follow
because it's like you were comparing two different kind of entities. I
tend to think more in term of branch (e.g. what's happened to the upper
branch and what's happened to the lower branch, rather than think in terms
of "before a point in time" and "after that point in time"). Because of
that, I constantly need to look back at the scheme to find out what is `A',
what is `Z' etc.
Some more comments below. Sorry for not spotting these earlier.
@@ -934,6 +934,95 @@ Figuring out why this works is left as an exercise to
the (advanced)
student. The gitlink:git-log[1], gitlink:git-diff-tree[1], and
gitlink:git-hash-object[1] man pages may prove helpful.
+[[history-advanced-topics]]
+Advanced topics
+---------------
+This section covers advanced topics that typically require more
+knowledge about git than the manual presented to this point.
+
+You may want to skip the section at first reading, and come back
I think the correct wording here is "on first reading". If a native
English speaker could confirm this...
On Nov 7, 2007, at 11:16 PM, Benoit Sigoure wrote:
Hi Steffen,
On Nov 7, 2007, at 10:50 PM, Steffen Prohaska wrote:
Some more comments below. Sorry for not spotting these earlier.
I'll took all your suggestions except for ...
[...]
quoted
+later when you have a better understanding of git.
+
+[[bisect-merges]]
+Why bisecting merge commits can be harder than bisecting linear
history
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
+The following text is based upon an email by Junio C. Hamano to
+the git mailing list
+(link:http://marc.info/?l=git&m=119403257315527&w=2[link:http://
marc.info/?l=git&m=119403257315527&w=2]).
+It was slightly adapted for this manual.
+
+Bisecting merges can be challenging due to the complexity of
+changes introduced at a merge. Bisecting through merges is not a
s/at a merge/& point/ ?
I'll replace the first sentence with
Using gitlink:git-bisect[1] on a history with merges can be challenging.
The details are explained in the remainder of the paragraph.
[...]
quoted
+added a new calling site for that function at commit Y. The
+commits from Z leading to B all assume the old semantics of that
+function and the callers and the callee are consistent with each
+other. There is no bug at B, either.
+
+You merge to create C. There is no textual conflict with this
+three way merge, and the result merges cleanly. You bisect
+this, because you found D is bad and you know Z was good. Your
+bisect will find that C (merge) is broken. Understandably so,
+as at C, the new calling site of the function added by the lower
+branch is not converted to the new semantics, while all the
+other calling sites that already existed at Z would have been
+converted by the merge. The new calling site has semantic
+adjustment needed, but you do not know that yet. You need to
s/adjustment/&s/
I'm not sure if plural is needed.
Steffen
--
Steffen Prohaska [off-list ref] <http://www.zib.de/prohaska/>
Zuse Institute Berlin, Takustraße 7, D-14195 Berlin-Dahlem, Germany
+49 (30) 841 85-337, fax -107
From: Johannes Sixt <hidden> Date: 2016-06-15 22:43:48
Steffen Prohaska schrieb:
+If you linearize the history by rebasing the lower branch on
+top of the upper, instead of merging, the bug becomes much easier to
+find and understand. Your history would instead be:
At this point I'm missing the words
The solution is ...
I.e.:
The solution is to linearize the history by rebasing the lower branch on
top of the upper, instead of merging. Now the bug becomes much easier to
find and understand. Your history would instead be:
-- Hannes
+If you linearize the history by rebasing the lower branch on
+top of the upper, instead of merging, the bug becomes much easier to
+find and understand. Your history would instead be:
At this point I'm missing the words
The solution is ...
I.e.:
The solution is to linearize the history by rebasing the lower
branch on
top of the upper, instead of merging. Now the bug becomes much
easier to
find and understand. Your history would instead be:
Hmm. It might be a solution if you did not publish history.
How about leaving the text as is and adding an introductory
paragraph at the beginning of the section?
I.e:
This section discusses how gitlink:git-bisect[1] plays
with differently shaped histories. If you did not yet
publish a branch you can use either gitlink:git-merge[1] or
gitlink:git-rebase[1] to integrate changes from a second
branch. The two approaches create differently shaped
histories. So it might be interesting to know about the
implications on gitlink:git-bisect[1].
Steffen
From: Johannes Sixt <hidden> Date: 2016-06-15 22:43:48
Steffen Prohaska schrieb:
On Nov 8, 2007, at 8:19 AM, Johannes Sixt wrote:
quoted
Steffen Prohaska schrieb:
quoted
+If you linearize the history by rebasing the lower branch on
+top of the upper, instead of merging, the bug becomes much easier to
+find and understand. Your history would instead be:
At this point I'm missing the words
The solution is ...
I.e.:
The solution is to linearize the history by rebasing the lower branch on
top of the upper, instead of merging. Now the bug becomes much easier to
find and understand. Your history would instead be:
Hmm. It might be a solution if you did not publish history.
This is about finding the commit that introduced a bug. Once you found it,
better: you know how to fix the bug, you are expected to throw away the
rebased branch, not to publish it! Maybe a note along these lines could be
appended:
Now that you know what caused the error (and how to fix it), throw away the
rebased branch, and commit a fix on top of D.
-- Hannes
From: Andreas Ericsson <hidden> Date: 2016-06-15 22:43:48
Johannes Sixt wrote:
Steffen Prohaska schrieb:
quoted
On Nov 8, 2007, at 8:19 AM, Johannes Sixt wrote:
quoted
Steffen Prohaska schrieb:
quoted
+If you linearize the history by rebasing the lower branch on
+top of the upper, instead of merging, the bug becomes much easier to
+find and understand. Your history would instead be:
At this point I'm missing the words
The solution is ...
I.e.:
The solution is to linearize the history by rebasing the lower branch on
top of the upper, instead of merging. Now the bug becomes much easier to
find and understand. Your history would instead be:
Hmm. It might be a solution if you did not publish history.
This is about finding the commit that introduced a bug. Once you found
it, better: you know how to fix the bug, you are expected to throw away
the rebased branch, not to publish it! Maybe a note along these lines
could be appended:
Now that you know what caused the error (and how to fix it), throw away
the rebased branch, and commit a fix on top of D.
Well, if rebasing becomes the standard for normal development, it's hardly
right to throw it away, is it? I like Steffen's suggestion better.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
From: Johannes Sixt <hidden> Date: 2016-06-15 22:43:48
Andreas Ericsson schrieb:
Johannes Sixt wrote:
quoted
Steffen Prohaska schrieb:
quoted
On Nov 8, 2007, at 8:19 AM, Johannes Sixt wrote:
quoted
Steffen Prohaska schrieb:
quoted
+If you linearize the history by rebasing the lower branch on
+top of the upper, instead of merging, the bug becomes much easier to
+find and understand. Your history would instead be:
At this point I'm missing the words
The solution is ...
I.e.:
The solution is to linearize the history by rebasing the lower
branch on
top of the upper, instead of merging. Now the bug becomes much
easier to
find and understand. Your history would instead be:
Hmm. It might be a solution if you did not publish history.
This is about finding the commit that introduced a bug. Once you found
it, better: you know how to fix the bug, you are expected to throw
away the rebased branch, not to publish it! Maybe a note along these
lines could be appended:
Now that you know what caused the error (and how to fix it), throw
away the rebased branch, and commit a fix on top of D.
Well, if rebasing becomes the standard for normal development, it's hardly
right to throw it away, is it? I like Steffen's suggestion better.
There is a big misunderstanding. The text that the patch amends is about
bisecting history that reveals that a merge commit breaks, which is not
helpful, and then how to find where and what and why the breakage really was
introduce.
And the answer to "how to find" is to rebase and bisect in the rebased history.
My initial complaint was that in the flow of reading the instructions the
pointer to "the solution" was missing. Rather, at the point where the reader
is supposed to think "ah, yes, that's how to do it", there is the
conditional statement "If you linearize history". My suggestion is to put a
big emphasis on the solution by using the words "The solution is".
Now, the user can *always* rebase one of the branches on top of the other,
even if both histories are already published. *But* if both were indeed
published, then the rebased history must be thrown away, and the only thing
you learnt from it was where and what and why the breakage really was
introduced.
Of course we could include a few "ifs" and "unlesses" (about published
histories), before suggesting to throw away rebased history. But once the
task is accomplished (find the bogus commit), throwing away the rebased
history (and continuing at commit D) is always correct, but keeping it (and
continuing at D*) is not.
-- Hannes
+If you linearize the history by rebasing the lower branch on
+top of the upper, instead of merging, the bug becomes much
easier to
+find and understand. Your history would instead be:
At this point I'm missing the words
The solution is ...
I.e.:
The solution is to linearize the history by rebasing the lower
branch on
top of the upper, instead of merging. Now the bug becomes much
easier to
find and understand. Your history would instead be:
Hmm. It might be a solution if you did not publish history.
This is about finding the commit that introduced a bug. Once you
found it, better: you know how to fix the bug, you are expected
to throw away the rebased branch, not to publish it! Maybe a note
along these lines could be appended:
Now that you know what caused the error (and how to fix it),
throw away the rebased branch, and commit a fix on top of D.
Well, if rebasing becomes the standard for normal development,
it's hardly
right to throw it away, is it? I like Steffen's suggestion better.
There is a big misunderstanding. The text that the patch amends is
about bisecting history that reveals that a merge commit breaks,
which is not helpful, and then how to find where and what and why
the breakage really was introduce.
And the answer to "how to find" is to rebase and bisect in the
rebased history.
Do you use rebase like this in real life?
I thought of the text as background information that might
be helpful for users who want do decide wether to merge or
to rebase. The problem described may be valuable information
supporting a decision about a recommended workflow for a group
of users.
My personal conclusion was: I'll accept the danger of complex
merges that might be hard to bisect. I now understand this
risk, but I nonetheless prefer the simplicity of a merge
based workflow. This avoids the danger that published history
gets rewritten.
But now I'm wondering if your suggestions of rebasing only for
locating the evil commit is feasible in reality. You may need
to solve a lot of merge conflicts if you rebase a larger part
of the history. If you do not have them in your rerere cache
this might be time consuming. ...
My initial complaint was that in the flow of reading the
instructions the pointer to "the solution" was missing. Rather, at
the point where the reader is supposed to think "ah, yes, that's
how to do it", there is the conditional statement "If you linearize
history". My suggestion is to put a big emphasis on the solution by
using the words "The solution is".
Now, the user can *always* rebase one of the branches on top of the
other, even if both histories are already published. *But* if both
were indeed published, then the rebased history must be thrown
away, and the only thing you learnt from it was where and what and
why the breakage really was introduced.
Of course we could include a few "ifs" and "unlesses" (about
published histories), before suggesting to throw away rebased
history. But once the task is accomplished (find the bogus commit),
throwing away the rebased history (and continuing at commit D) is
always correct, but keeping it (and continuing at D*) is not.
... So, again, the question for me is if someone does use
rebase in reality in the way that you suggests. Do you? Does
someone else?
Steffen
From: Johannes Sixt <hidden> Date: 2016-06-15 22:43:48
Steffen Prohaska schrieb:
On Nov 8, 2007, at 10:53 AM, Johannes Sixt wrote:
quoted
The text that the patch amends is
about bisecting history that reveals that a merge commit breaks, which
is not helpful, and then how to find where and what and why the
breakage really was introduce.
And the answer to "how to find" is to rebase and bisect in the rebased
history.
Do you use rebase like this in real life?
Why is this relevant?
You've written a superb addendum to the user manual, but IT TALKS ABOUT
BISECTION, and is not a guideline when to use merges and when to rebase.
It better not be meant as such. Consider an integrator who has just merged
two histories, both of which are available publically. Pushing out a rebased
history IS NOT AN OPTION. If the poor fellow for the heck of it has no
choice but to find the bogus commit, then your instructions are worth a
thousand bucks - even if the rebased history is otherwise useless -, but any
guidelines how to construct histories are IRRELEVANT for his case.
But now I'm wondering if your suggestions of rebasing only for
locating the evil commit is feasible in reality. You may need
to solve a lot of merge conflicts if you rebase a larger part
of the history. If you do not have them in your rerere cache
this might be time consuming. ...
During the rebase you will see the same conflicts that you also had during
the merge, even simpler ones (because they are - hopefully - broken down
into smaller pieces). If your merge was clean (as was suggested in the
patch), then you won't see a lot of conflicts during the rebase, either.
-- Hannes
From: Andreas Ericsson <hidden> Date: 2016-06-15 22:43:48
Steffen Prohaska wrote:
On Nov 8, 2007, at 10:53 AM, Johannes Sixt wrote:
quoted
Andreas Ericsson schrieb:
quoted
Johannes Sixt wrote:
quoted
Steffen Prohaska schrieb:
quoted
On Nov 8, 2007, at 8:19 AM, Johannes Sixt wrote:
quoted
Steffen Prohaska schrieb:
quoted
+If you linearize the history by rebasing the lower branch on
+top of the upper, instead of merging, the bug becomes much
easier to
+find and understand. Your history would instead be:
At this point I'm missing the words
The solution is ...
I.e.:
The solution is to linearize the history by rebasing the lower
branch on
top of the upper, instead of merging. Now the bug becomes much
easier to
find and understand. Your history would instead be:
Hmm. It might be a solution if you did not publish history.
This is about finding the commit that introduced a bug. Once you
found it, better: you know how to fix the bug, you are expected to
throw away the rebased branch, not to publish it! Maybe a note along
these lines could be appended:
Now that you know what caused the error (and how to fix it), throw
away the rebased branch, and commit a fix on top of D.
Well, if rebasing becomes the standard for normal development, it's
hardly
right to throw it away, is it? I like Steffen's suggestion better.
There is a big misunderstanding. The text that the patch amends is
about bisecting history that reveals that a merge commit breaks, which
is not helpful, and then how to find where and what and why the
breakage really was introduce.
And the answer to "how to find" is to rebase and bisect in the rebased
history.
Do you use rebase like this in real life?
I thought of the text as background information that might
be helpful for users who want do decide wether to merge or
to rebase. The problem described may be valuable information
supporting a decision about a recommended workflow for a group
of users.
My personal conclusion was: I'll accept the danger of complex
merges that might be hard to bisect. I now understand this
risk, but I nonetheless prefer the simplicity of a merge
based workflow. This avoids the danger that published history
gets rewritten.
But now I'm wondering if your suggestions of rebasing only for
locating the evil commit is feasible in reality. You may need
to solve a lot of merge conflicts if you rebase a larger part
of the history. If you do not have them in your rerere cache
this might be time consuming. ...
It is no great chore to put one merge-parent on top of another
and then re-run bisect on the result. git-bisect could even be
taught to do that by itself.
quoted
My initial complaint was that in the flow of reading the instructions
the pointer to "the solution" was missing. Rather, at the point where
the reader is supposed to think "ah, yes, that's how to do it", there
is the conditional statement "If you linearize history". My suggestion
is to put a big emphasis on the solution by using the words "The
solution is".
Now, the user can *always* rebase one of the branches on top of the
other, even if both histories are already published. *But* if both
were indeed published, then the rebased history must be thrown away,
and the only thing you learnt from it was where and what and why the
breakage really was introduced.
Of course we could include a few "ifs" and "unlesses" (about published
histories), before suggesting to throw away rebased history. But once
the task is accomplished (find the bogus commit), throwing away the
rebased history (and continuing at commit D) is always correct, but
keeping it (and continuing at D*) is not.
... So, again, the question for me is if someone does use
rebase in reality in the way that you suggests. Do you?
I don't, but if I'd thought a bit further I would have on at least one
occasion in the past. Instead I spent two days manually auditing every
commit of several branches.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
On Nov 8, 2007, at 1:54 PM, Steffen Prohaska wrote:
Do you use rebase like this in real life?
I thought of the text as background information that might
be helpful for users who want do decide wether to merge or
to rebase. The problem described may be valuable information
supporting a decision about a recommended workflow for a group
of users.
You're missing the point. Johannes suggested that you rebase *only*
for bisecting purpose. Once you find the culprit commit, throw away
your rebased stuff. I've never thought about doing this myself, but
it's a very clever way of tackling this problem. It's slightly less
convenient if you need to bisect a large portion of the history (that
involves many branches and merges) because in this case we'd like to
have a magic git-linearize-history <start-treeish> <end-treeish>.
Unless this is already easily doable with git-rebase?
So to summarize (untested):
git merge topic
make check
<omg something's broken>
git reset --hard HEAD~1 # undo the merge
git checkout -b wtf
git rebase topic master
git bisect ...
<OK I found the culprit>
git checkout master
git branch -D wtf
git merge --no-commit topic
<fix the problem>
git commit # merge done, semantic glitch fixed
Correct me if I'm wrong.
This has *nothing* to do with the fact that you use merge or rebase
to do whatever you were doing.
--
Benoit Sigoure aka Tsuna
EPITA Research and Development Laboratory
The text that the patch amends is about bisecting history that
reveals that a merge commit breaks, which is not helpful, and
then how to find where and what and why the breakage really was
introduce.
And the answer to "how to find" is to rebase and bisect in the
rebased history.
Do you use rebase like this in real life?
Why is this relevant?
Well, I don't want to give recommendations that are not tested
in real life. Maybe the solution turns out to be less practical
than it should be theoretically.
You've written a superb addendum to the user manual, but IT TALKS
ABOUT BISECTION, and is not a guideline when to use merges and when
to rebase.
BTW, I only took what Junio wrote during a recent discussion
on the list, polished it a bit and sent it as a patch. I'm
only the editor, not the original author. That doesn't mean
I wouldn't care about the text. I'm willing to improve the text.
But all the cheers really should go to Junio.
It better not be meant as such. Consider an integrator who has just
merged two histories, both of which are available publically.
Pushing out a rebased history IS NOT AN OPTION. If the poor fellow
for the heck of it has no choice but to find the bogus commit, then
your instructions are worth a thousand bucks - even if the rebased
history is otherwise useless -, but any guidelines how to construct
histories are IRRELEVANT for his case.
Ok, I see your point. I'll mention these points.
quoted
But now I'm wondering if your suggestions of rebasing only for
locating the evil commit is feasible in reality. You may need
to solve a lot of merge conflicts if you rebase a larger part
of the history. If you do not have them in your rerere cache
this might be time consuming. ...
During the rebase you will see the same conflicts that you also had
during the merge, even simpler ones (because they are - hopefully -
broken down into smaller pieces). If your merge was clean (as was
suggested in the patch), then you won't see a lot of conflicts
during the rebase, either.
Yeah. I'll try to mention this at an appropriate place.
Steffen
On Nov 8, 2007, at 1:54 PM, Steffen Prohaska wrote:
quoted
Do you use rebase like this in real life?
I thought of the text as background information that might
be helpful for users who want do decide wether to merge or
to rebase. The problem described may be valuable information
supporting a decision about a recommended workflow for a group
of users.
You're missing the point. Johannes suggested that you rebase
*only* for bisecting purpose. Once you find the culprit commit,
throw away your rebased stuff.
I got this point. I also noted that it might be time consuming
if you need to resolve conflicts.
The original discussion in which Junio explained the problem
with bisecting merges was about workflows. The question then was
if users should _always_ rebase if possible to make bisecting
easier. It was really a workflow question.
Well, the context of the original discussion is no longer
present in the patch I sent. Therefore, Johannes' comments
absolutely make sense. Actually I find them really inspiring as
I have not thought before about rebasing temporarily, just for
finding a commit. Now I learnt that this could be a useful tool.
I've never thought about doing this myself, but it's a very clever
way of tackling this problem.
Apparently, you haven't thought about this solution either ;)
Steffen
From: Johannes Schindelin <hidden> Date: 2016-06-15 22:43:48
Hi,
On Thu, 8 Nov 2007, Benoit Sigoure wrote:
On Nov 8, 2007, at 1:54 PM, Steffen Prohaska wrote:
quoted
Do you use rebase like this in real life?
I thought of the text as background information that might be helpful
for users who want do decide wether to merge or to rebase. The problem
described may be valuable information supporting a decision about a
recommended workflow for a group of users.
You're missing the point. Johannes suggested that you rebase *only* for
bisecting purpose. Once you find the culprit commit, throw away your
rebased stuff.
Just to clear things up: it was the other Johannes who suggested it.
But I strongly advise not to rebase before bisecting, since you could very
well end up changing the behaviour of the program by rebasing it. Even to
a point where you cannot bisect it any longer, for example when the merge
of two branches contains an important fix without which the combined
branches (or even parts of them) will not even compile.
Last time I checked, however, bisect worked like a charm even on
a history with complicated ancestry.
Ciao,
Dscho
From: Brian Gernhardt <hidden> Date: 2016-06-15 22:43:48
On Nov 8, 2007, at 9:51 AM, Benoit Sigoure wrote:
You're missing the point. Johannes suggested that you rebase *only*
for bisecting purpose. Once you find the culprit commit, throw away
your rebased stuff. I've never thought about doing this myself, but
it's a very clever way of tackling this problem. It's slightly less
convenient if you need to bisect a large portion of the history
(that involves many branches and merges) because in this case we'd
like to have a magic git-linearize-history <start-treeish> <end-
treeish>. Unless this is already easily doable with git-rebase?
I don't think you have to linearize it before bisecting. If you
bisect and discover that it was due to a merge, then you can rebase
*that merge* to discover what part of the merge caused the issue.
~~ Brian
This commits adds a discussion of the challenge of bisecting
merge commits to the user manual. The original author is
Junio C Hamano [off-list ref], who posted the text to
the mailing list:
<http://marc.info/?l=git&m=119403257315527&w=2>.
The text from the email is slightly adapted for the manual.
The discussion is added to "Exploring git history" in a
sub-section titled "Advanced topics". The discussion requires
detailed knowledge about git. It is assumed that the reader will
skip advanced topics on first reading. At least the text suggest
to do so.
The text includes suggestions and fixed by
Ralf Wildenhues [off-list ref],
Benoit Sigoure [off-list ref],
Johannes Sixt [off-list ref].
Signed-off-by: Steffen Prohaska <redacted>
---
Documentation/user-manual.txt | 104 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 104 insertions(+), 0 deletions(-)
Next try.
The text now contains an introductory paragraph, proposes rebase as a
'solution', and recommends to throw away the rebased branch.
Steffen
@@ -934,6 +934,110 @@ Figuring out why this works is left as an exercise to the (advanced) student. The gitlink:git-log[1], gitlink:git-diff-tree[1], and gitlink:git-hash-object[1] man pages may prove helpful.+[[history-advanced-topics]]+Advanced topics+---------------+This section covers advanced topics that typically require more+knowledge about git than the manual presented to this point.++You may want to skip the section on first reading, and come back+later when you have a better understanding of git.++[[bisect-merges]]+Why bisecting merge commits can be harder than bisecting linear history+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+This section discusses how gitlink:git-bisect[1] plays+with differently shaped histories. If you did not yet+publish a branch you can use either gitlink:git-merge[1] or+gitlink:git-rebase[1] to integrate changes from a second+branch. The two approaches create differently shaped+histories. This section discusses the implications on+gitlink:git-bisect[1]. If the history is already published+temporarily rebasing can still be helpful for bisecting.++The following text is based upon an email by Junio C. Hamano to+the git mailing list+(link:http://marc.info/?l=git&m=119403257315527&w=2[link:http://marc.info/?l=git&m=119403257315527&w=2]).+It was slightly adapted for this manual.++Using gitlink:git-bisect[1] on a history with merges can be challenging.+Bisecting through merges is not a+technical problem. The real problem is what to do when the+culprit turns out to be a merge commit. How to spot what really+is wrong, and figure out how to fix. The problem is not for the+tool but for the human, and it is real.++Imagine this history.++................................................+ ---Z---o---X---...---o---A---C---D+ \ /+ o---o---Y---...---o---B+................................................++Suppose that on the upper development line, the meaning of one+of the functions that existed at Z was changed at commit X. The+commits from Z leading to A change both the function's+implementation and all calling sites that existed at Z, as well+as new calling sites they add, to be consistent. There is no+bug at A.++Suppose that in the meantime the lower development line somebody+added a new calling site for that function at commit Y. The+commits from Z leading to B all assume the old semantics of that+function and the callers and the callee are consistent with each+other. There is no bug at B, either.++You merge to create C. There is no textual conflict with this+three way merge, and the result merges cleanly. You bisect+this, because you found D is bad and you know Z was good. Your+bisect will find that C (merge) is broken. Understandably so,+as at C, the new calling site of the function added by the lower+branch is not converted to the new semantics, while all the+other calling sites that already existed at Z would have been+converted by the merge. The new calling site has semantic+adjustment needed, but you do not know that yet. You need to+find out that that is the cause of the breakage by looking at the+merge commit C and the history leading to it.++How would you do that?++Both "git diff A C" and "git diff B C" would be an enormous patch.+Each of them essentially shows the whole change on each branch+since they diverged. The developers may have well behaved to+create good commits that follow the "commit small, commit often,+commit well contained units" mantra, and each individual commit+leading from Z to A and from Z to B may be easy to review and+understand, but looking at these small and easily reviewable+steps alone would not let you spot the breakage. You need to+have a global picture of what the upper branch did (and+among many, one of them is to change the semantics of that+particular function) and look first at the huge "diff A C"+(which shows the change the lower branch introduces), and see if+that huge change is consistent with what have been done between+Z and A.++A solution is to linearize the history by rebasing the lower+branch on top of the upper, instead of merging. There were no+textual conflicts in the original three way merge. So there+should not be conflicts during rebase either. Now the bug becomes+much easier to find and understand. Your history would instead+be:++................................................................+ ---Z---o---X--...---o---A---o---o---Y*--...---o---B*--D*+................................................................++and there is a single commit Y* between A and B* that introduced+the new calling site that still uses the old semantics of the+function, even though that was already modified at X. "git show+Y*" will be a much smaller patch than "git diff A C" and it is+much easier to deal with.++Now that you know what caused the error (and how to fix it),+throw away the rebased branch, and commit a fix on top of D.++ [[Developing-with-git]] Developing with git ===================